/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/
/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId]) {
/******/ 			return installedModules[moduleId].exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			i: moduleId,
/******/ 			l: false,
/******/ 			exports: {}
/******/ 		};
/******/
/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ 		// Flag the module as loaded
/******/ 		module.l = true;
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/
/******/
/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;
/******/
/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;
/******/
/******/ 	// define getter function for harmony exports
/******/ 	__webpack_require__.d = function(exports, name, getter) {
/******/ 		if(!__webpack_require__.o(exports, name)) {
/******/ 			Object.defineProperty(exports, name, {
/******/ 				configurable: false,
/******/ 				enumerable: true,
/******/ 				get: getter
/******/ 			});
/******/ 		}
/******/ 	};
/******/
/******/ 	// getDefaultExport function for compatibility with non-harmony modules
/******/ 	__webpack_require__.n = function(module) {
/******/ 		var getter = module && module.__esModule ?
/******/ 			function getDefault() { return module['default']; } :
/******/ 			function getModuleExports() { return module; };
/******/ 		__webpack_require__.d(getter, 'a', getter);
/******/ 		return getter;
/******/ 	};
/******/
/******/ 	// Object.prototype.hasOwnProperty.call
/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";
/******/
/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(__webpack_require__.s = 5);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

    var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
    * jQuery JavaScript Library v3.2.1
    * https://jquery.com/
    *
    * Includes Sizzle.js
    * https://sizzlejs.com/
    *
    * Copyright JS Foundation and other contributors
    * Released under the MIT license
    * https://jquery.org/license
    *
    * Date: 2017-03-20T18:59Z
    */
   ( function( global, factory ) {
   
       "use strict";
   
       if ( typeof module === "object" && typeof module.exports === "object" ) {
   
           // For CommonJS and CommonJS-like environments where a proper `window`
           // is present, execute the factory and get jQuery.
           // For environments that do not have a `window` with a `document`
           // (such as Node.js), expose a factory as module.exports.
           // This accentuates the need for the creation of a real `window`.
           // e.g. var jQuery = require("jquery")(window);
           // See ticket #14549 for more info.
           module.exports = global.document ?
               factory( global, true ) :
               function( w ) {
                   if ( !w.document ) {
                       throw new Error( "jQuery requires a window with a document" );
                   }
                   return factory( w );
               };
       } else {
           factory( global );
       }
   
   // Pass this if window is not defined yet
   } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
   
   // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
   // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
   // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
   // enough that all such attempts are guarded in a try block.
   "use strict";
   
   var arr = [];
   
   var document = window.document;
   
   var getProto = Object.getPrototypeOf;
   
   var slice = arr.slice;
   
   var concat = arr.concat;
   
   var push = arr.push;
   
   var indexOf = arr.indexOf;
   
   var class2type = {};
   
   var toString = class2type.toString;
   
   var hasOwn = class2type.hasOwnProperty;
   
   var fnToString = hasOwn.toString;
   
   var ObjectFunctionString = fnToString.call( Object );
   
   var support = {};
   
   
   
       function DOMEval( code, doc ) {
           doc = doc || document;
   
           var script = doc.createElement( "script" );
   
           script.text = code;
           doc.head.appendChild( script ).parentNode.removeChild( script );
       }
   /* global Symbol */
   // Defining this global in .eslintrc.json would create a danger of using the global
   // unguarded in another place, it seems safer to define global only for this module
   
   
   
   var
       version = "3.2.1",
   
       // Define a local copy of jQuery
       jQuery = function( selector, context ) {
   
           // The jQuery object is actually just the init constructor 'enhanced'
           // Need init if jQuery is called (just allow error to be thrown if not included)
           return new jQuery.fn.init( selector, context );
       },
   
       // Support: Android <=4.0 only
       // Make sure we trim BOM and NBSP
       rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
   
       // Matches dashed string for camelizing
       rmsPrefix = /^-ms-/,
       rdashAlpha = /-([a-z])/g,
   
       // Used by jQuery.camelCase as callback to replace()
       fcamelCase = function( all, letter ) {
           return letter.toUpperCase();
       };
   
   jQuery.fn = jQuery.prototype = {
   
       // The current version of jQuery being used
       jquery: version,
   
       constructor: jQuery,
   
       // The default length of a jQuery object is 0
       length: 0,
   
       toArray: function() {
           return slice.call( this );
       },
   
       // Get the Nth element in the matched element set OR
       // Get the whole matched element set as a clean array
       get: function( num ) {
   
           // Return all the elements in a clean array
           if ( num == null ) {
               return slice.call( this );
           }
   
           // Return just the one element from the set
           return num < 0 ? this[ num + this.length ] : this[ num ];
       },
   
       // Take an array of elements and push it onto the stack
       // (returning the new matched element set)
       pushStack: function( elems ) {
   
           // Build a new jQuery matched element set
           var ret = jQuery.merge( this.constructor(), elems );
   
           // Add the old object onto the stack (as a reference)
           ret.prevObject = this;
   
           // Return the newly-formed element set
           return ret;
       },
   
       // Execute a callback for every element in the matched set.
       each: function( callback ) {
           return jQuery.each( this, callback );
       },
   
       map: function( callback ) {
           return this.pushStack( jQuery.map( this, function( elem, i ) {
               return callback.call( elem, i, elem );
           } ) );
       },
   
       slice: function() {
           return this.pushStack( slice.apply( this, arguments ) );
       },
   
       first: function() {
           return this.eq( 0 );
       },
   
       last: function() {
           return this.eq( -1 );
       },
   
       eq: function( i ) {
           var len = this.length,
               j = +i + ( i < 0 ? len : 0 );
           return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
       },
   
       end: function() {
           return this.prevObject || this.constructor();
       },
   
       // For internal use only.
       // Behaves like an Array's method, not like a jQuery method.
       push: push,
       sort: arr.sort,
       splice: arr.splice
   };
   
   jQuery.extend = jQuery.fn.extend = function() {
       var options, name, src, copy, copyIsArray, clone,
           target = arguments[ 0 ] || {},
           i = 1,
           length = arguments.length,
           deep = false;
   
       // Handle a deep copy situation
       if ( typeof target === "boolean" ) {
           deep = target;
   
           // Skip the boolean and the target
           target = arguments[ i ] || {};
           i++;
       }
   
       // Handle case when target is a string or something (possible in deep copy)
       if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
           target = {};
       }
   
       // Extend jQuery itself if only one argument is passed
       if ( i === length ) {
           target = this;
           i--;
       }
   
       for ( ; i < length; i++ ) {
   
           // Only deal with non-null/undefined values
           if ( ( options = arguments[ i ] ) != null ) {
   
               // Extend the base object
               for ( name in options ) {
                   src = target[ name ];
                   copy = options[ name ];
   
                   // Prevent never-ending loop
                   if ( target === copy ) {
                       continue;
                   }
   
                   // Recurse if we're merging plain objects or arrays
                   if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                       ( copyIsArray = Array.isArray( copy ) ) ) ) {
   
                       if ( copyIsArray ) {
                           copyIsArray = false;
                           clone = src && Array.isArray( src ) ? src : [];
   
                       } else {
                           clone = src && jQuery.isPlainObject( src ) ? src : {};
                       }
   
                       // Never move original objects, clone them
                       target[ name ] = jQuery.extend( deep, clone, copy );
   
                   // Don't bring in undefined values
                   } else if ( copy !== undefined ) {
                       target[ name ] = copy;
                   }
               }
           }
       }
   
       // Return the modified object
       return target;
   };
   
   jQuery.extend( {
   
       // Unique for each copy of jQuery on the page
       expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
   
       // Assume jQuery is ready without the ready module
       isReady: true,
   
       error: function( msg ) {
           throw new Error( msg );
       },
   
       noop: function() {},
   
       isFunction: function( obj ) {
           return jQuery.type( obj ) === "function";
       },
   
       isWindow: function( obj ) {
           return obj != null && obj === obj.window;
       },
   
       isNumeric: function( obj ) {
   
           // As of jQuery 3.0, isNumeric is limited to
           // strings and numbers (primitives or objects)
           // that can be coerced to finite numbers (gh-2662)
           var type = jQuery.type( obj );
           return ( type === "number" || type === "string" ) &&
   
               // parseFloat NaNs numeric-cast false positives ("")
               // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
               // subtraction forces infinities to NaN
               !isNaN( obj - parseFloat( obj ) );
       },
   
       isPlainObject: function( obj ) {
           var proto, Ctor;
   
           // Detect obvious negatives
           // Use toString instead of jQuery.type to catch host objects
           if ( !obj || toString.call( obj ) !== "[object Object]" ) {
               return false;
           }
   
           proto = getProto( obj );
   
           // Objects with no prototype (e.g., `Object.create( null )`) are plain
           if ( !proto ) {
               return true;
           }
   
           // Objects with prototype are plain iff they were constructed by a global Object function
           Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
           return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
       },
   
       isEmptyObject: function( obj ) {
   
           /* eslint-disable no-unused-vars */
           // See https://github.com/eslint/eslint/issues/6125
           var name;
   
           for ( name in obj ) {
               return false;
           }
           return true;
       },
   
       type: function( obj ) {
           if ( obj == null ) {
               return obj + "";
           }
   
           // Support: Android <=2.3 only (functionish RegExp)
           return typeof obj === "object" || typeof obj === "function" ?
               class2type[ toString.call( obj ) ] || "object" :
               typeof obj;
       },
   
       // Evaluates a script in a global context
       globalEval: function( code ) {
           DOMEval( code );
       },
   
       // Convert dashed to camelCase; used by the css and data modules
       // Support: IE <=9 - 11, Edge 12 - 13
       // Microsoft forgot to hump their vendor prefix (#9572)
       camelCase: function( string ) {
           return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
       },
   
       each: function( obj, callback ) {
           var length, i = 0;
   
           if ( isArrayLike( obj ) ) {
               length = obj.length;
               for ( ; i < length; i++ ) {
                   if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                       break;
                   }
               }
           } else {
               for ( i in obj ) {
                   if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
                       break;
                   }
               }
           }
   
           return obj;
       },
   
       // Support: Android <=4.0 only
       trim: function( text ) {
           return text == null ?
               "" :
               ( text + "" ).replace( rtrim, "" );
       },
   
       // results is for internal usage only
       makeArray: function( arr, results ) {
           var ret = results || [];
   
           if ( arr != null ) {
               if ( isArrayLike( Object( arr ) ) ) {
                   jQuery.merge( ret,
                       typeof arr === "string" ?
                       [ arr ] : arr
                   );
               } else {
                   push.call( ret, arr );
               }
           }
   
           return ret;
       },
   
       inArray: function( elem, arr, i ) {
           return arr == null ? -1 : indexOf.call( arr, elem, i );
       },
   
       // Support: Android <=4.0 only, PhantomJS 1 only
       // push.apply(_, arraylike) throws on ancient WebKit
       merge: function( first, second ) {
           var len = +second.length,
               j = 0,
               i = first.length;
   
           for ( ; j < len; j++ ) {
               first[ i++ ] = second[ j ];
           }
   
           first.length = i;
   
           return first;
       },
   
       grep: function( elems, callback, invert ) {
           var callbackInverse,
               matches = [],
               i = 0,
               length = elems.length,
               callbackExpect = !invert;
   
           // Go through the array, only saving the items
           // that pass the validator function
           for ( ; i < length; i++ ) {
               callbackInverse = !callback( elems[ i ], i );
               if ( callbackInverse !== callbackExpect ) {
                   matches.push( elems[ i ] );
               }
           }
   
           return matches;
       },
   
       // arg is for internal usage only
       map: function( elems, callback, arg ) {
           var length, value,
               i = 0,
               ret = [];
   
           // Go through the array, translating each of the items to their new values
           if ( isArrayLike( elems ) ) {
               length = elems.length;
               for ( ; i < length; i++ ) {
                   value = callback( elems[ i ], i, arg );
   
                   if ( value != null ) {
                       ret.push( value );
                   }
               }
   
           // Go through every key on the object,
           } else {
               for ( i in elems ) {
                   value = callback( elems[ i ], i, arg );
   
                   if ( value != null ) {
                       ret.push( value );
                   }
               }
           }
   
           // Flatten any nested arrays
           return concat.apply( [], ret );
       },
   
       // A global GUID counter for objects
       guid: 1,
   
       // Bind a function to a context, optionally partially applying any
       // arguments.
       proxy: function( fn, context ) {
           var tmp, args, proxy;
   
           if ( typeof context === "string" ) {
               tmp = fn[ context ];
               context = fn;
               fn = tmp;
           }
   
           // Quick check to determine if target is callable, in the spec
           // this throws a TypeError, but we will just return undefined.
           if ( !jQuery.isFunction( fn ) ) {
               return undefined;
           }
   
           // Simulated bind
           args = slice.call( arguments, 2 );
           proxy = function() {
               return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
           };
   
           // Set the guid of unique handler to the same of original handler, so it can be removed
           proxy.guid = fn.guid = fn.guid || jQuery.guid++;
   
           return proxy;
       },
   
       now: Date.now,
   
       // jQuery.support is not used in Core but other projects attach their
       // properties to it so it needs to exist.
       support: support
   } );
   
   if ( typeof Symbol === "function" ) {
       jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
   }
   
   // Populate the class2type map
   jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
   function( i, name ) {
       class2type[ "[object " + name + "]" ] = name.toLowerCase();
   } );
   
   function isArrayLike( obj ) {
   
       // Support: real iOS 8.2 only (not reproducible in simulator)
       // `in` check used to prevent JIT error (gh-2145)
       // hasOwn isn't used here due to false negatives
       // regarding Nodelist length in IE
       var length = !!obj && "length" in obj && obj.length,
           type = jQuery.type( obj );
   
       if ( type === "function" || jQuery.isWindow( obj ) ) {
           return false;
       }
   
       return type === "array" || length === 0 ||
           typeof length === "number" && length > 0 && ( length - 1 ) in obj;
   }
   var Sizzle =
   /*!
    * Sizzle CSS Selector Engine v2.3.3
    * https://sizzlejs.com/
    *
    * Copyright jQuery Foundation and other contributors
    * Released under the MIT license
    * http://jquery.org/license
    *
    * Date: 2016-08-08
    */
   (function( window ) {
   
   var i,
       support,
       Expr,
       getText,
       isXML,
       tokenize,
       compile,
       select,
       outermostContext,
       sortInput,
       hasDuplicate,
   
       // Local document vars
       setDocument,
       document,
       docElem,
       documentIsHTML,
       rbuggyQSA,
       rbuggyMatches,
       matches,
       contains,
   
       // Instance-specific data
       expando = "sizzle" + 1 * new Date(),
       preferredDoc = window.document,
       dirruns = 0,
       done = 0,
       classCache = createCache(),
       tokenCache = createCache(),
       compilerCache = createCache(),
       sortOrder = function( a, b ) {
           if ( a === b ) {
               hasDuplicate = true;
           }
           return 0;
       },
   
       // Instance methods
       hasOwn = ({}).hasOwnProperty,
       arr = [],
       pop = arr.pop,
       push_native = arr.push,
       push = arr.push,
       slice = arr.slice,
       // Use a stripped-down indexOf as it's faster than native
       // https://jsperf.com/thor-indexof-vs-for/5
       indexOf = function( list, elem ) {
           var i = 0,
               len = list.length;
           for ( ; i < len; i++ ) {
               if ( list[i] === elem ) {
                   return i;
               }
           }
           return -1;
       },
   
       booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
   
       // Regular expressions
   
       // http://www.w3.org/TR/css3-selectors/#whitespace
       whitespace = "[\\x20\\t\\r\\n\\f]",
   
       // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
       identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
   
       // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
       attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
           // Operator (capture 2)
           "*([*^$|!~]?=)" + whitespace +
           // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
           "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
           "*\\]",
   
       pseudos = ":(" + identifier + ")(?:\\((" +
           // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
           // 1. quoted (capture 3; capture 4 or capture 5)
           "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
           // 2. simple (capture 6)
           "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
           // 3. anything else (capture 2)
           ".*" +
           ")\\)|)",
   
       // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
       rwhitespace = new RegExp( whitespace + "+", "g" ),
       rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
   
       rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
       rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
   
       rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
   
       rpseudo = new RegExp( pseudos ),
       ridentifier = new RegExp( "^" + identifier + "$" ),
   
       matchExpr = {
           "ID": new RegExp( "^#(" + identifier + ")" ),
           "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
           "TAG": new RegExp( "^(" + identifier + "|[*])" ),
           "ATTR": new RegExp( "^" + attributes ),
           "PSEUDO": new RegExp( "^" + pseudos ),
           "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
               "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
               "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
           "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
           // For use in libraries implementing .is()
           // We use this for POS matching in `select`
           "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
               whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
       },
   
       rinputs = /^(?:input|select|textarea|button)$/i,
       rheader = /^h\d$/i,
   
       rnative = /^[^{]+\{\s*\[native \w/,
   
       // Easily-parseable/retrievable ID or TAG or CLASS selectors
       rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
   
       rsibling = /[+~]/,
   
       // CSS escapes
       // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
       runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
       funescape = function( _, escaped, escapedWhitespace ) {
           var high = "0x" + escaped - 0x10000;
           // NaN means non-codepoint
           // Support: Firefox<24
           // Workaround erroneous numeric interpretation of +"0x"
           return high !== high || escapedWhitespace ?
               escaped :
               high < 0 ?
                   // BMP codepoint
                   String.fromCharCode( high + 0x10000 ) :
                   // Supplemental Plane codepoint (surrogate pair)
                   String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
       },
   
       // CSS string/identifier serialization
       // https://drafts.csswg.org/cssom/#common-serializing-idioms
       rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
       fcssescape = function( ch, asCodePoint ) {
           if ( asCodePoint ) {
   
               // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
               if ( ch === "\0" ) {
                   return "\uFFFD";
               }
   
               // Control characters and (dependent upon position) numbers get escaped as code points
               return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
           }
   
           // Other potentially-special ASCII characters get backslash-escaped
           return "\\" + ch;
       },
   
       // Used for iframes
       // See setDocument()
       // Removing the function wrapper causes a "Permission Denied"
       // error in IE
       unloadHandler = function() {
           setDocument();
       },
   
       disabledAncestor = addCombinator(
           function( elem ) {
               return elem.disabled === true && ("form" in elem || "label" in elem);
           },
           { dir: "parentNode", next: "legend" }
       );
   
   // Optimize for push.apply( _, NodeList )
   try {
       push.apply(
           (arr = slice.call( preferredDoc.childNodes )),
           preferredDoc.childNodes
       );
       // Support: Android<4.0
       // Detect silently failing push.apply
       arr[ preferredDoc.childNodes.length ].nodeType;
   } catch ( e ) {
       push = { apply: arr.length ?
   
           // Leverage slice if possible
           function( target, els ) {
               push_native.apply( target, slice.call(els) );
           } :
   
           // Support: IE<9
           // Otherwise append directly
           function( target, els ) {
               var j = target.length,
                   i = 0;
               // Can't trust NodeList.length
               while ( (target[j++] = els[i++]) ) {}
               target.length = j - 1;
           }
       };
   }
   
   function Sizzle( selector, context, results, seed ) {
       var m, i, elem, nid, match, groups, newSelector,
           newContext = context && context.ownerDocument,
   
           // nodeType defaults to 9, since context defaults to document
           nodeType = context ? context.nodeType : 9;
   
       results = results || [];
   
       // Return early from calls with invalid selector or context
       if ( typeof selector !== "string" || !selector ||
           nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
   
           return results;
       }
   
       // Try to shortcut find operations (as opposed to filters) in HTML documents
       if ( !seed ) {
   
           if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
               setDocument( context );
           }
           context = context || document;
   
           if ( documentIsHTML ) {
   
               // If the selector is sufficiently simple, try using a "get*By*" DOM method
               // (excepting DocumentFragment context, where the methods don't exist)
               if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
   
                   // ID selector
                   if ( (m = match[1]) ) {
   
                       // Document context
                       if ( nodeType === 9 ) {
                           if ( (elem = context.getElementById( m )) ) {
   
                               // Support: IE, Opera, Webkit
                               // TODO: identify versions
                               // getElementById can match elements by name instead of ID
                               if ( elem.id === m ) {
                                   results.push( elem );
                                   return results;
                               }
                           } else {
                               return results;
                           }
   
                       // Element context
                       } else {
   
                           // Support: IE, Opera, Webkit
                           // TODO: identify versions
                           // getElementById can match elements by name instead of ID
                           if ( newContext && (elem = newContext.getElementById( m )) &&
                               contains( context, elem ) &&
                               elem.id === m ) {
   
                               results.push( elem );
                               return results;
                           }
                       }
   
                   // Type selector
                   } else if ( match[2] ) {
                       push.apply( results, context.getElementsByTagName( selector ) );
                       return results;
   
                   // Class selector
                   } else if ( (m = match[3]) && support.getElementsByClassName &&
                       context.getElementsByClassName ) {
   
                       push.apply( results, context.getElementsByClassName( m ) );
                       return results;
                   }
               }
   
               // Take advantage of querySelectorAll
               if ( support.qsa &&
                   !compilerCache[ selector + " " ] &&
                   (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
   
                   if ( nodeType !== 1 ) {
                       newContext = context;
                       newSelector = selector;
   
                   // qSA looks outside Element context, which is not what we want
                   // Thanks to Andrew Dupont for this workaround technique
                   // Support: IE <=8
                   // Exclude object elements
                   } else if ( context.nodeName.toLowerCase() !== "object" ) {
   
                       // Capture the context ID, setting it first if necessary
                       if ( (nid = context.getAttribute( "id" )) ) {
                           nid = nid.replace( rcssescape, fcssescape );
                       } else {
                           context.setAttribute( "id", (nid = expando) );
                       }
   
                       // Prefix every selector in the list
                       groups = tokenize( selector );
                       i = groups.length;
                       while ( i-- ) {
                           groups[i] = "#" + nid + " " + toSelector( groups[i] );
                       }
                       newSelector = groups.join( "," );
   
                       // Expand context for sibling selectors
                       newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
                           context;
                   }
   
                   if ( newSelector ) {
                       try {
                           push.apply( results,
                               newContext.querySelectorAll( newSelector )
                           );
                           return results;
                       } catch ( qsaError ) {
                       } finally {
                           if ( nid === expando ) {
                               context.removeAttribute( "id" );
                           }
                       }
                   }
               }
           }
       }
   
       // All others
       return select( selector.replace( rtrim, "$1" ), context, results, seed );
   }
   
   /**
    * Create key-value caches of limited size
    * @returns {function(string, object)} Returns the Object data after storing it on itself with
    *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
    *	deleting the oldest entry
    */
   function createCache() {
       var keys = [];
   
       function cache( key, value ) {
           // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
           if ( keys.push( key + " " ) > Expr.cacheLength ) {
               // Only keep the most recent entries
               delete cache[ keys.shift() ];
           }
           return (cache[ key + " " ] = value);
       }
       return cache;
   }
   
   /**
    * Mark a function for special use by Sizzle
    * @param {Function} fn The function to mark
    */
   function markFunction( fn ) {
       fn[ expando ] = true;
       return fn;
   }
   
   /**
    * Support testing using an element
    * @param {Function} fn Passed the created element and returns a boolean result
    */
   function assert( fn ) {
       var el = document.createElement("fieldset");
   
       try {
           return !!fn( el );
       } catch (e) {
           return false;
       } finally {
           // Remove from its parent by default
           if ( el.parentNode ) {
               el.parentNode.removeChild( el );
           }
           // release memory in IE
           el = null;
       }
   }
   
   /**
    * Adds the same handler for all of the specified attrs
    * @param {String} attrs Pipe-separated list of attributes
    * @param {Function} handler The method that will be applied
    */
   function addHandle( attrs, handler ) {
       var arr = attrs.split("|"),
           i = arr.length;
   
       while ( i-- ) {
           Expr.attrHandle[ arr[i] ] = handler;
       }
   }
   
   /**
    * Checks document order of two siblings
    * @param {Element} a
    * @param {Element} b
    * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
    */
   function siblingCheck( a, b ) {
       var cur = b && a,
           diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
               a.sourceIndex - b.sourceIndex;
   
       // Use IE sourceIndex if available on both nodes
       if ( diff ) {
           return diff;
       }
   
       // Check if b follows a
       if ( cur ) {
           while ( (cur = cur.nextSibling) ) {
               if ( cur === b ) {
                   return -1;
               }
           }
       }
   
       return a ? 1 : -1;
   }
   
   /**
    * Returns a function to use in pseudos for input types
    * @param {String} type
    */
   function createInputPseudo( type ) {
       return function( elem ) {
           var name = elem.nodeName.toLowerCase();
           return name === "input" && elem.type === type;
       };
   }
   
   /**
    * Returns a function to use in pseudos for buttons
    * @param {String} type
    */
   function createButtonPseudo( type ) {
       return function( elem ) {
           var name = elem.nodeName.toLowerCase();
           return (name === "input" || name === "button") && elem.type === type;
       };
   }
   
   /**
    * Returns a function to use in pseudos for :enabled/:disabled
    * @param {Boolean} disabled true for :disabled; false for :enabled
    */
   function createDisabledPseudo( disabled ) {
   
       // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
       return function( elem ) {
   
           // Only certain elements can match :enabled or :disabled
           // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
           // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
           if ( "form" in elem ) {
   
               // Check for inherited disabledness on relevant non-disabled elements:
               // * listed form-associated elements in a disabled fieldset
               //   https://html.spec.whatwg.org/multipage/forms.html#category-listed
               //   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
               // * option elements in a disabled optgroup
               //   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
               // All such elements have a "form" property.
               if ( elem.parentNode && elem.disabled === false ) {
   
                   // Option elements defer to a parent optgroup if present
                   if ( "label" in elem ) {
                       if ( "label" in elem.parentNode ) {
                           return elem.parentNode.disabled === disabled;
                       } else {
                           return elem.disabled === disabled;
                       }
                   }
   
                   // Support: IE 6 - 11
                   // Use the isDisabled shortcut property to check for disabled fieldset ancestors
                   return elem.isDisabled === disabled ||
   
                       // Where there is no isDisabled, check manually
                       /* jshint -W018 */
                       elem.isDisabled !== !disabled &&
                           disabledAncestor( elem ) === disabled;
               }
   
               return elem.disabled === disabled;
   
           // Try to winnow out elements that can't be disabled before trusting the disabled property.
           // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
           // even exist on them, let alone have a boolean value.
           } else if ( "label" in elem ) {
               return elem.disabled === disabled;
           }
   
           // Remaining elements are neither :enabled nor :disabled
           return false;
       };
   }
   
   /**
    * Returns a function to use in pseudos for positionals
    * @param {Function} fn
    */
   function createPositionalPseudo( fn ) {
       return markFunction(function( argument ) {
           argument = +argument;
           return markFunction(function( seed, matches ) {
               var j,
                   matchIndexes = fn( [], seed.length, argument ),
                   i = matchIndexes.length;
   
               // Match elements found at the specified indexes
               while ( i-- ) {
                   if ( seed[ (j = matchIndexes[i]) ] ) {
                       seed[j] = !(matches[j] = seed[j]);
                   }
               }
           });
       });
   }
   
   /**
    * Checks a node for validity as a Sizzle context
    * @param {Element|Object=} context
    * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
    */
   function testContext( context ) {
       return context && typeof context.getElementsByTagName !== "undefined" && context;
   }
   
   // Expose support vars for convenience
   support = Sizzle.support = {};
   
   /**
    * Detects XML nodes
    * @param {Element|Object} elem An element or a document
    * @returns {Boolean} True iff elem is a non-HTML XML node
    */
   isXML = Sizzle.isXML = function( elem ) {
       // documentElement is verified for cases where it doesn't yet exist
       // (such as loading iframes in IE - #4833)
       var documentElement = elem && (elem.ownerDocument || elem).documentElement;
       return documentElement ? documentElement.nodeName !== "HTML" : false;
   };
   
   /**
    * Sets document-related variables once based on the current document
    * @param {Element|Object} [doc] An element or document object to use to set the document
    * @returns {Object} Returns the current document
    */
   setDocument = Sizzle.setDocument = function( node ) {
       var hasCompare, subWindow,
           doc = node ? node.ownerDocument || node : preferredDoc;
   
       // Return early if doc is invalid or already selected
       if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
           return document;
       }
   
       // Update global variables
       document = doc;
       docElem = document.documentElement;
       documentIsHTML = !isXML( document );
   
       // Support: IE 9-11, Edge
       // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
       if ( preferredDoc !== document &&
           (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
   
           // Support: IE 11, Edge
           if ( subWindow.addEventListener ) {
               subWindow.addEventListener( "unload", unloadHandler, false );
   
           // Support: IE 9 - 10 only
           } else if ( subWindow.attachEvent ) {
               subWindow.attachEvent( "onunload", unloadHandler );
           }
       }
   
       /* Attributes
       ---------------------------------------------------------------------- */
   
       // Support: IE<8
       // Verify that getAttribute really returns attributes and not properties
       // (excepting IE8 booleans)
       support.attributes = assert(function( el ) {
           el.className = "i";
           return !el.getAttribute("className");
       });
   
       /* getElement(s)By*
       ---------------------------------------------------------------------- */
   
       // Check if getElementsByTagName("*") returns only elements
       support.getElementsByTagName = assert(function( el ) {
           el.appendChild( document.createComment("") );
           return !el.getElementsByTagName("*").length;
       });
   
       // Support: IE<9
       support.getElementsByClassName = rnative.test( document.getElementsByClassName );
   
       // Support: IE<10
       // Check if getElementById returns elements by name
       // The broken getElementById methods don't pick up programmatically-set names,
       // so use a roundabout getElementsByName test
       support.getById = assert(function( el ) {
           docElem.appendChild( el ).id = expando;
           return !document.getElementsByName || !document.getElementsByName( expando ).length;
       });
   
       // ID filter and find
       if ( support.getById ) {
           Expr.filter["ID"] = function( id ) {
               var attrId = id.replace( runescape, funescape );
               return function( elem ) {
                   return elem.getAttribute("id") === attrId;
               };
           };
           Expr.find["ID"] = function( id, context ) {
               if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
                   var elem = context.getElementById( id );
                   return elem ? [ elem ] : [];
               }
           };
       } else {
           Expr.filter["ID"] =  function( id ) {
               var attrId = id.replace( runescape, funescape );
               return function( elem ) {
                   var node = typeof elem.getAttributeNode !== "undefined" &&
                       elem.getAttributeNode("id");
                   return node && node.value === attrId;
               };
           };
   
           // Support: IE 6 - 7 only
           // getElementById is not reliable as a find shortcut
           Expr.find["ID"] = function( id, context ) {
               if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
                   var node, i, elems,
                       elem = context.getElementById( id );
   
                   if ( elem ) {
   
                       // Verify the id attribute
                       node = elem.getAttributeNode("id");
                       if ( node && node.value === id ) {
                           return [ elem ];
                       }
   
                       // Fall back on getElementsByName
                       elems = context.getElementsByName( id );
                       i = 0;
                       while ( (elem = elems[i++]) ) {
                           node = elem.getAttributeNode("id");
                           if ( node && node.value === id ) {
                               return [ elem ];
                           }
                       }
                   }
   
                   return [];
               }
           };
       }
   
       // Tag
       Expr.find["TAG"] = support.getElementsByTagName ?
           function( tag, context ) {
               if ( typeof context.getElementsByTagName !== "undefined" ) {
                   return context.getElementsByTagName( tag );
   
               // DocumentFragment nodes don't have gEBTN
               } else if ( support.qsa ) {
                   return context.querySelectorAll( tag );
               }
           } :
   
           function( tag, context ) {
               var elem,
                   tmp = [],
                   i = 0,
                   // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
                   results = context.getElementsByTagName( tag );
   
               // Filter out possible comments
               if ( tag === "*" ) {
                   while ( (elem = results[i++]) ) {
                       if ( elem.nodeType === 1 ) {
                           tmp.push( elem );
                       }
                   }
   
                   return tmp;
               }
               return results;
           };
   
       // Class
       Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
           if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
               return context.getElementsByClassName( className );
           }
       };
   
       /* QSA/matchesSelector
       ---------------------------------------------------------------------- */
   
       // QSA and matchesSelector support
   
       // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
       rbuggyMatches = [];
   
       // qSa(:focus) reports false when true (Chrome 21)
       // We allow this because of a bug in IE8/9 that throws an error
       // whenever `document.activeElement` is accessed on an iframe
       // So, we allow :focus to pass through QSA all the time to avoid the IE error
       // See https://bugs.jquery.com/ticket/13378
       rbuggyQSA = [];
   
       if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
           // Build QSA regex
           // Regex strategy adopted from Diego Perini
           assert(function( el ) {
               // Select is set to empty string on purpose
               // This is to test IE's treatment of not explicitly
               // setting a boolean content attribute,
               // since its presence should be enough
               // https://bugs.jquery.com/ticket/12359
               docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
                   "<select id='" + expando + "-\r\\' msallowcapture=''>" +
                   "<option selected=''></option></select>";
   
               // Support: IE8, Opera 11-12.16
               // Nothing should be selected when empty strings follow ^= or $= or *=
               // The test attribute must be unknown in Opera but "safe" for WinRT
               // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
               if ( el.querySelectorAll("[msallowcapture^='']").length ) {
                   rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
               }
   
               // Support: IE8
               // Boolean attributes and "value" are not treated correctly
               if ( !el.querySelectorAll("[selected]").length ) {
                   rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
               }
   
               // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
               if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
                   rbuggyQSA.push("~=");
               }
   
               // Webkit/Opera - :checked should return selected option elements
               // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
               // IE8 throws error here and will not see later tests
               if ( !el.querySelectorAll(":checked").length ) {
                   rbuggyQSA.push(":checked");
               }
   
               // Support: Safari 8+, iOS 8+
               // https://bugs.webkit.org/show_bug.cgi?id=136851
               // In-page `selector#id sibling-combinator selector` fails
               if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
                   rbuggyQSA.push(".#.+[+~]");
               }
           });
   
           assert(function( el ) {
               el.innerHTML = "<a href='' disabled='disabled'></a>" +
                   "<select disabled='disabled'><option/></select>";
   
               // Support: Windows 8 Native Apps
               // The type and name attributes are restricted during .innerHTML assignment
               var input = document.createElement("input");
               input.setAttribute( "type", "hidden" );
               el.appendChild( input ).setAttribute( "name", "D" );
   
               // Support: IE8
               // Enforce case-sensitivity of name attribute
               if ( el.querySelectorAll("[name=d]").length ) {
                   rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
               }
   
               // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
               // IE8 throws error here and will not see later tests
               if ( el.querySelectorAll(":enabled").length !== 2 ) {
                   rbuggyQSA.push( ":enabled", ":disabled" );
               }
   
               // Support: IE9-11+
               // IE's :disabled selector does not pick up the children of disabled fieldsets
               docElem.appendChild( el ).disabled = true;
               if ( el.querySelectorAll(":disabled").length !== 2 ) {
                   rbuggyQSA.push( ":enabled", ":disabled" );
               }
   
               // Opera 10-11 does not throw on post-comma invalid pseudos
               el.querySelectorAll("*,:x");
               rbuggyQSA.push(",.*:");
           });
       }
   
       if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
           docElem.webkitMatchesSelector ||
           docElem.mozMatchesSelector ||
           docElem.oMatchesSelector ||
           docElem.msMatchesSelector) )) ) {
   
           assert(function( el ) {
               // Check to see if it's possible to do matchesSelector
               // on a disconnected node (IE 9)
               support.disconnectedMatch = matches.call( el, "*" );
   
               // This should fail with an exception
               // Gecko does not error, returns false instead
               matches.call( el, "[s!='']:x" );
               rbuggyMatches.push( "!=", pseudos );
           });
       }
   
       rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
       rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
   
       /* Contains
       ---------------------------------------------------------------------- */
       hasCompare = rnative.test( docElem.compareDocumentPosition );
   
       // Element contains another
       // Purposefully self-exclusive
       // As in, an element does not contain itself
       contains = hasCompare || rnative.test( docElem.contains ) ?
           function( a, b ) {
               var adown = a.nodeType === 9 ? a.documentElement : a,
                   bup = b && b.parentNode;
               return a === bup || !!( bup && bup.nodeType === 1 && (
                   adown.contains ?
                       adown.contains( bup ) :
                       a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
               ));
           } :
           function( a, b ) {
               if ( b ) {
                   while ( (b = b.parentNode) ) {
                       if ( b === a ) {
                           return true;
                       }
                   }
               }
               return false;
           };
   
       /* Sorting
       ---------------------------------------------------------------------- */
   
       // Document order sorting
       sortOrder = hasCompare ?
       function( a, b ) {
   
           // Flag for duplicate removal
           if ( a === b ) {
               hasDuplicate = true;
               return 0;
           }
   
           // Sort on method existence if only one input has compareDocumentPosition
           var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
           if ( compare ) {
               return compare;
           }
   
           // Calculate position if both inputs belong to the same document
           compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
               a.compareDocumentPosition( b ) :
   
               // Otherwise we know they are disconnected
               1;
   
           // Disconnected nodes
           if ( compare & 1 ||
               (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
   
               // Choose the first element that is related to our preferred document
               if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
                   return -1;
               }
               if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
                   return 1;
               }
   
               // Maintain original order
               return sortInput ?
                   ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
                   0;
           }
   
           return compare & 4 ? -1 : 1;
       } :
       function( a, b ) {
           // Exit early if the nodes are identical
           if ( a === b ) {
               hasDuplicate = true;
               return 0;
           }
   
           var cur,
               i = 0,
               aup = a.parentNode,
               bup = b.parentNode,
               ap = [ a ],
               bp = [ b ];
   
           // Parentless nodes are either documents or disconnected
           if ( !aup || !bup ) {
               return a === document ? -1 :
                   b === document ? 1 :
                   aup ? -1 :
                   bup ? 1 :
                   sortInput ?
                   ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
                   0;
   
           // If the nodes are siblings, we can do a quick check
           } else if ( aup === bup ) {
               return siblingCheck( a, b );
           }
   
           // Otherwise we need full lists of their ancestors for comparison
           cur = a;
           while ( (cur = cur.parentNode) ) {
               ap.unshift( cur );
           }
           cur = b;
           while ( (cur = cur.parentNode) ) {
               bp.unshift( cur );
           }
   
           // Walk down the tree looking for a discrepancy
           while ( ap[i] === bp[i] ) {
               i++;
           }
   
           return i ?
               // Do a sibling check if the nodes have a common ancestor
               siblingCheck( ap[i], bp[i] ) :
   
               // Otherwise nodes in our document sort first
               ap[i] === preferredDoc ? -1 :
               bp[i] === preferredDoc ? 1 :
               0;
       };
   
       return document;
   };
   
   Sizzle.matches = function( expr, elements ) {
       return Sizzle( expr, null, null, elements );
   };
   
   Sizzle.matchesSelector = function( elem, expr ) {
       // Set document vars if needed
       if ( ( elem.ownerDocument || elem ) !== document ) {
           setDocument( elem );
       }
   
       // Make sure that attribute selectors are quoted
       expr = expr.replace( rattributeQuotes, "='$1']" );
   
       if ( support.matchesSelector && documentIsHTML &&
           !compilerCache[ expr + " " ] &&
           ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
           ( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
   
           try {
               var ret = matches.call( elem, expr );
   
               // IE 9's matchesSelector returns false on disconnected nodes
               if ( ret || support.disconnectedMatch ||
                       // As well, disconnected nodes are said to be in a document
                       // fragment in IE 9
                       elem.document && elem.document.nodeType !== 11 ) {
                   return ret;
               }
           } catch (e) {}
       }
   
       return Sizzle( expr, document, null, [ elem ] ).length > 0;
   };
   
   Sizzle.contains = function( context, elem ) {
       // Set document vars if needed
       if ( ( context.ownerDocument || context ) !== document ) {
           setDocument( context );
       }
       return contains( context, elem );
   };
   
   Sizzle.attr = function( elem, name ) {
       // Set document vars if needed
       if ( ( elem.ownerDocument || elem ) !== document ) {
           setDocument( elem );
       }
   
       var fn = Expr.attrHandle[ name.toLowerCase() ],
           // Don't get fooled by Object.prototype properties (jQuery #13807)
           val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
               fn( elem, name, !documentIsHTML ) :
               undefined;
   
       return val !== undefined ?
           val :
           support.attributes || !documentIsHTML ?
               elem.getAttribute( name ) :
               (val = elem.getAttributeNode(name)) && val.specified ?
                   val.value :
                   null;
   };
   
   Sizzle.escape = function( sel ) {
       return (sel + "").replace( rcssescape, fcssescape );
   };
   
   Sizzle.error = function( msg ) {
       throw new Error( "Syntax error, unrecognized expression: " + msg );
   };
   
   /**
    * Document sorting and removing duplicates
    * @param {ArrayLike} results
    */
   Sizzle.uniqueSort = function( results ) {
       var elem,
           duplicates = [],
           j = 0,
           i = 0;
   
       // Unless we *know* we can detect duplicates, assume their presence
       hasDuplicate = !support.detectDuplicates;
       sortInput = !support.sortStable && results.slice( 0 );
       results.sort( sortOrder );
   
       if ( hasDuplicate ) {
           while ( (elem = results[i++]) ) {
               if ( elem === results[ i ] ) {
                   j = duplicates.push( i );
               }
           }
           while ( j-- ) {
               results.splice( duplicates[ j ], 1 );
           }
       }
   
       // Clear input after sorting to release objects
       // See https://github.com/jquery/sizzle/pull/225
       sortInput = null;
   
       return results;
   };
   
   /**
    * Utility function for retrieving the text value of an array of DOM nodes
    * @param {Array|Element} elem
    */
   getText = Sizzle.getText = function( elem ) {
       var node,
           ret = "",
           i = 0,
           nodeType = elem.nodeType;
   
       if ( !nodeType ) {
           // If no nodeType, this is expected to be an array
           while ( (node = elem[i++]) ) {
               // Do not traverse comment nodes
               ret += getText( node );
           }
       } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
           // Use textContent for elements
           // innerText usage removed for consistency of new lines (jQuery #11153)
           if ( typeof elem.textContent === "string" ) {
               return elem.textContent;
           } else {
               // Traverse its children
               for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                   ret += getText( elem );
               }
           }
       } else if ( nodeType === 3 || nodeType === 4 ) {
           return elem.nodeValue;
       }
       // Do not include comment or processing instruction nodes
   
       return ret;
   };
   
   Expr = Sizzle.selectors = {
   
       // Can be adjusted by the user
       cacheLength: 50,
   
       createPseudo: markFunction,
   
       match: matchExpr,
   
       attrHandle: {},
   
       find: {},
   
       relative: {
           ">": { dir: "parentNode", first: true },
           " ": { dir: "parentNode" },
           "+": { dir: "previousSibling", first: true },
           "~": { dir: "previousSibling" }
       },
   
       preFilter: {
           "ATTR": function( match ) {
               match[1] = match[1].replace( runescape, funescape );
   
               // Move the given value to match[3] whether quoted or unquoted
               match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
   
               if ( match[2] === "~=" ) {
                   match[3] = " " + match[3] + " ";
               }
   
               return match.slice( 0, 4 );
           },
   
           "CHILD": function( match ) {
               /* matches from matchExpr["CHILD"]
                   1 type (only|nth|...)
                   2 what (child|of-type)
                   3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
                   4 xn-component of xn+y argument ([+-]?\d*n|)
                   5 sign of xn-component
                   6 x of xn-component
                   7 sign of y-component
                   8 y of y-component
               */
               match[1] = match[1].toLowerCase();
   
               if ( match[1].slice( 0, 3 ) === "nth" ) {
                   // nth-* requires argument
                   if ( !match[3] ) {
                       Sizzle.error( match[0] );
                   }
   
                   // numeric x and y parameters for Expr.filter.CHILD
                   // remember that false/true cast respectively to 0/1
                   match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
                   match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
   
               // other types prohibit arguments
               } else if ( match[3] ) {
                   Sizzle.error( match[0] );
               }
   
               return match;
           },
   
           "PSEUDO": function( match ) {
               var excess,
                   unquoted = !match[6] && match[2];
   
               if ( matchExpr["CHILD"].test( match[0] ) ) {
                   return null;
               }
   
               // Accept quoted arguments as-is
               if ( match[3] ) {
                   match[2] = match[4] || match[5] || "";
   
               // Strip excess characters from unquoted arguments
               } else if ( unquoted && rpseudo.test( unquoted ) &&
                   // Get excess from tokenize (recursively)
                   (excess = tokenize( unquoted, true )) &&
                   // advance to the next closing parenthesis
                   (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
   
                   // excess is a negative index
                   match[0] = match[0].slice( 0, excess );
                   match[2] = unquoted.slice( 0, excess );
               }
   
               // Return only captures needed by the pseudo filter method (type and argument)
               return match.slice( 0, 3 );
           }
       },
   
       filter: {
   
           "TAG": function( nodeNameSelector ) {
               var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
               return nodeNameSelector === "*" ?
                   function() { return true; } :
                   function( elem ) {
                       return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
                   };
           },
   
           "CLASS": function( className ) {
               var pattern = classCache[ className + " " ];
   
               return pattern ||
                   (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
                   classCache( className, function( elem ) {
                       return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
                   });
           },
   
           "ATTR": function( name, operator, check ) {
               return function( elem ) {
                   var result = Sizzle.attr( elem, name );
   
                   if ( result == null ) {
                       return operator === "!=";
                   }
                   if ( !operator ) {
                       return true;
                   }
   
                   result += "";
   
                   return operator === "=" ? result === check :
                       operator === "!=" ? result !== check :
                       operator === "^=" ? check && result.indexOf( check ) === 0 :
                       operator === "*=" ? check && result.indexOf( check ) > -1 :
                       operator === "$=" ? check && result.slice( -check.length ) === check :
                       operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
                       operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
                       false;
               };
           },
   
           "CHILD": function( type, what, argument, first, last ) {
               var simple = type.slice( 0, 3 ) !== "nth",
                   forward = type.slice( -4 ) !== "last",
                   ofType = what === "of-type";
   
               return first === 1 && last === 0 ?
   
                   // Shortcut for :nth-*(n)
                   function( elem ) {
                       return !!elem.parentNode;
                   } :
   
                   function( elem, context, xml ) {
                       var cache, uniqueCache, outerCache, node, nodeIndex, start,
                           dir = simple !== forward ? "nextSibling" : "previousSibling",
                           parent = elem.parentNode,
                           name = ofType && elem.nodeName.toLowerCase(),
                           useCache = !xml && !ofType,
                           diff = false;
   
                       if ( parent ) {
   
                           // :(first|last|only)-(child|of-type)
                           if ( simple ) {
                               while ( dir ) {
                                   node = elem;
                                   while ( (node = node[ dir ]) ) {
                                       if ( ofType ?
                                           node.nodeName.toLowerCase() === name :
                                           node.nodeType === 1 ) {
   
                                           return false;
                                       }
                                   }
                                   // Reverse direction for :only-* (if we haven't yet done so)
                                   start = dir = type === "only" && !start && "nextSibling";
                               }
                               return true;
                           }
   
                           start = [ forward ? parent.firstChild : parent.lastChild ];
   
                           // non-xml :nth-child(...) stores cache data on `parent`
                           if ( forward && useCache ) {
   
                               // Seek `elem` from a previously-cached index
   
                               // ...in a gzip-friendly way
                               node = parent;
                               outerCache = node[ expando ] || (node[ expando ] = {});
   
                               // Support: IE <9 only
                               // Defend against cloned attroperties (jQuery gh-1709)
                               uniqueCache = outerCache[ node.uniqueID ] ||
                                   (outerCache[ node.uniqueID ] = {});
   
                               cache = uniqueCache[ type ] || [];
                               nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
                               diff = nodeIndex && cache[ 2 ];
                               node = nodeIndex && parent.childNodes[ nodeIndex ];
   
                               while ( (node = ++nodeIndex && node && node[ dir ] ||
   
                                   // Fallback to seeking `elem` from the start
                                   (diff = nodeIndex = 0) || start.pop()) ) {
   
                                   // When found, cache indexes on `parent` and break
                                   if ( node.nodeType === 1 && ++diff && node === elem ) {
                                       uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
                                       break;
                                   }
                               }
   
                           } else {
                               // Use previously-cached element index if available
                               if ( useCache ) {
                                   // ...in a gzip-friendly way
                                   node = elem;
                                   outerCache = node[ expando ] || (node[ expando ] = {});
   
                                   // Support: IE <9 only
                                   // Defend against cloned attroperties (jQuery gh-1709)
                                   uniqueCache = outerCache[ node.uniqueID ] ||
                                       (outerCache[ node.uniqueID ] = {});
   
                                   cache = uniqueCache[ type ] || [];
                                   nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
                                   diff = nodeIndex;
                               }
   
                               // xml :nth-child(...)
                               // or :nth-last-child(...) or :nth(-last)?-of-type(...)
                               if ( diff === false ) {
                                   // Use the same loop as above to seek `elem` from the start
                                   while ( (node = ++nodeIndex && node && node[ dir ] ||
                                       (diff = nodeIndex = 0) || start.pop()) ) {
   
                                       if ( ( ofType ?
                                           node.nodeName.toLowerCase() === name :
                                           node.nodeType === 1 ) &&
                                           ++diff ) {
   
                                           // Cache the index of each encountered element
                                           if ( useCache ) {
                                               outerCache = node[ expando ] || (node[ expando ] = {});
   
                                               // Support: IE <9 only
                                               // Defend against cloned attroperties (jQuery gh-1709)
                                               uniqueCache = outerCache[ node.uniqueID ] ||
                                                   (outerCache[ node.uniqueID ] = {});
   
                                               uniqueCache[ type ] = [ dirruns, diff ];
                                           }
   
                                           if ( node === elem ) {
                                               break;
                                           }
                                       }
                                   }
                               }
                           }
   
                           // Incorporate the offset, then check against cycle size
                           diff -= last;
                           return diff === first || ( diff % first === 0 && diff / first >= 0 );
                       }
                   };
           },
   
           "PSEUDO": function( pseudo, argument ) {
               // pseudo-class names are case-insensitive
               // http://www.w3.org/TR/selectors/#pseudo-classes
               // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
               // Remember that setFilters inherits from pseudos
               var args,
                   fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
                       Sizzle.error( "unsupported pseudo: " + pseudo );
   
               // The user may use createPseudo to indicate that
               // arguments are needed to create the filter function
               // just as Sizzle does
               if ( fn[ expando ] ) {
                   return fn( argument );
               }
   
               // But maintain support for old signatures
               if ( fn.length > 1 ) {
                   args = [ pseudo, pseudo, "", argument ];
                   return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
                       markFunction(function( seed, matches ) {
                           var idx,
                               matched = fn( seed, argument ),
                               i = matched.length;
                           while ( i-- ) {
                               idx = indexOf( seed, matched[i] );
                               seed[ idx ] = !( matches[ idx ] = matched[i] );
                           }
                       }) :
                       function( elem ) {
                           return fn( elem, 0, args );
                       };
               }
   
               return fn;
           }
       },
   
       pseudos: {
           // Potentially complex pseudos
           "not": markFunction(function( selector ) {
               // Trim the selector passed to compile
               // to avoid treating leading and trailing
               // spaces as combinators
               var input = [],
                   results = [],
                   matcher = compile( selector.replace( rtrim, "$1" ) );
   
               return matcher[ expando ] ?
                   markFunction(function( seed, matches, context, xml ) {
                       var elem,
                           unmatched = matcher( seed, null, xml, [] ),
                           i = seed.length;
   
                       // Match elements unmatched by `matcher`
                       while ( i-- ) {
                           if ( (elem = unmatched[i]) ) {
                               seed[i] = !(matches[i] = elem);
                           }
                       }
                   }) :
                   function( elem, context, xml ) {
                       input[0] = elem;
                       matcher( input, null, xml, results );
                       // Don't keep the element (issue #299)
                       input[0] = null;
                       return !results.pop();
                   };
           }),
   
           "has": markFunction(function( selector ) {
               return function( elem ) {
                   return Sizzle( selector, elem ).length > 0;
               };
           }),
   
           "contains": markFunction(function( text ) {
               text = text.replace( runescape, funescape );
               return function( elem ) {
                   return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
               };
           }),
   
           // "Whether an element is represented by a :lang() selector
           // is based solely on the element's language value
           // being equal to the identifier C,
           // or beginning with the identifier C immediately followed by "-".
           // The matching of C against the element's language value is performed case-insensitively.
           // The identifier C does not have to be a valid language name."
           // http://www.w3.org/TR/selectors/#lang-pseudo
           "lang": markFunction( function( lang ) {
               // lang value must be a valid identifier
               if ( !ridentifier.test(lang || "") ) {
                   Sizzle.error( "unsupported lang: " + lang );
               }
               lang = lang.replace( runescape, funescape ).toLowerCase();
               return function( elem ) {
                   var elemLang;
                   do {
                       if ( (elemLang = documentIsHTML ?
                           elem.lang :
                           elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
   
                           elemLang = elemLang.toLowerCase();
                           return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
                       }
                   } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
                   return false;
               };
           }),
   
           // Miscellaneous
           "target": function( elem ) {
               var hash = window.location && window.location.hash;
               return hash && hash.slice( 1 ) === elem.id;
           },
   
           "root": function( elem ) {
               return elem === docElem;
           },
   
           "focus": function( elem ) {
               return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
           },
   
           // Boolean properties
           "enabled": createDisabledPseudo( false ),
           "disabled": createDisabledPseudo( true ),
   
           "checked": function( elem ) {
               // In CSS3, :checked should return both checked and selected elements
               // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
               var nodeName = elem.nodeName.toLowerCase();
               return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
           },
   
           "selected": function( elem ) {
               // Accessing this property makes selected-by-default
               // options in Safari work properly
               if ( elem.parentNode ) {
                   elem.parentNode.selectedIndex;
               }
   
               return elem.selected === true;
           },
   
           // Contents
           "empty": function( elem ) {
               // http://www.w3.org/TR/selectors/#empty-pseudo
               // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
               //   but not by others (comment: 8; processing instruction: 7; etc.)
               // nodeType < 6 works because attributes (2) do not appear as children
               for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
                   if ( elem.nodeType < 6 ) {
                       return false;
                   }
               }
               return true;
           },
   
           "parent": function( elem ) {
               return !Expr.pseudos["empty"]( elem );
           },
   
           // Element/input types
           "header": function( elem ) {
               return rheader.test( elem.nodeName );
           },
   
           "input": function( elem ) {
               return rinputs.test( elem.nodeName );
           },
   
           "button": function( elem ) {
               var name = elem.nodeName.toLowerCase();
               return name === "input" && elem.type === "button" || name === "button";
           },
   
           "text": function( elem ) {
               var attr;
               return elem.nodeName.toLowerCase() === "input" &&
                   elem.type === "text" &&
   
                   // Support: IE<8
                   // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
                   ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
           },
   
           // Position-in-collection
           "first": createPositionalPseudo(function() {
               return [ 0 ];
           }),
   
           "last": createPositionalPseudo(function( matchIndexes, length ) {
               return [ length - 1 ];
           }),
   
           "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
               return [ argument < 0 ? argument + length : argument ];
           }),
   
           "even": createPositionalPseudo(function( matchIndexes, length ) {
               var i = 0;
               for ( ; i < length; i += 2 ) {
                   matchIndexes.push( i );
               }
               return matchIndexes;
           }),
   
           "odd": createPositionalPseudo(function( matchIndexes, length ) {
               var i = 1;
               for ( ; i < length; i += 2 ) {
                   matchIndexes.push( i );
               }
               return matchIndexes;
           }),
   
           "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
               var i = argument < 0 ? argument + length : argument;
               for ( ; --i >= 0; ) {
                   matchIndexes.push( i );
               }
               return matchIndexes;
           }),
   
           "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
               var i = argument < 0 ? argument + length : argument;
               for ( ; ++i < length; ) {
                   matchIndexes.push( i );
               }
               return matchIndexes;
           })
       }
   };
   
   Expr.pseudos["nth"] = Expr.pseudos["eq"];
   
   // Add button/input type pseudos
   for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
       Expr.pseudos[ i ] = createInputPseudo( i );
   }
   for ( i in { submit: true, reset: true } ) {
       Expr.pseudos[ i ] = createButtonPseudo( i );
   }
   
   // Easy API for creating new setFilters
   function setFilters() {}
   setFilters.prototype = Expr.filters = Expr.pseudos;
   Expr.setFilters = new setFilters();
   
   tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
       var matched, match, tokens, type,
           soFar, groups, preFilters,
           cached = tokenCache[ selector + " " ];
   
       if ( cached ) {
           return parseOnly ? 0 : cached.slice( 0 );
       }
   
       soFar = selector;
       groups = [];
       preFilters = Expr.preFilter;
   
       while ( soFar ) {
   
           // Comma and first run
           if ( !matched || (match = rcomma.exec( soFar )) ) {
               if ( match ) {
                   // Don't consume trailing commas as valid
                   soFar = soFar.slice( match[0].length ) || soFar;
               }
               groups.push( (tokens = []) );
           }
   
           matched = false;
   
           // Combinators
           if ( (match = rcombinators.exec( soFar )) ) {
               matched = match.shift();
               tokens.push({
                   value: matched,
                   // Cast descendant combinators to space
                   type: match[0].replace( rtrim, " " )
               });
               soFar = soFar.slice( matched.length );
           }
   
           // Filters
           for ( type in Expr.filter ) {
               if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
                   (match = preFilters[ type ]( match ))) ) {
                   matched = match.shift();
                   tokens.push({
                       value: matched,
                       type: type,
                       matches: match
                   });
                   soFar = soFar.slice( matched.length );
               }
           }
   
           if ( !matched ) {
               break;
           }
       }
   
       // Return the length of the invalid excess
       // if we're just parsing
       // Otherwise, throw an error or return tokens
       return parseOnly ?
           soFar.length :
           soFar ?
               Sizzle.error( selector ) :
               // Cache the tokens
               tokenCache( selector, groups ).slice( 0 );
   };
   
   function toSelector( tokens ) {
       var i = 0,
           len = tokens.length,
           selector = "";
       for ( ; i < len; i++ ) {
           selector += tokens[i].value;
       }
       return selector;
   }
   
   function addCombinator( matcher, combinator, base ) {
       var dir = combinator.dir,
           skip = combinator.next,
           key = skip || dir,
           checkNonElements = base && key === "parentNode",
           doneName = done++;
   
       return combinator.first ?
           // Check against closest ancestor/preceding element
           function( elem, context, xml ) {
               while ( (elem = elem[ dir ]) ) {
                   if ( elem.nodeType === 1 || checkNonElements ) {
                       return matcher( elem, context, xml );
                   }
               }
               return false;
           } :
   
           // Check against all ancestor/preceding elements
           function( elem, context, xml ) {
               var oldCache, uniqueCache, outerCache,
                   newCache = [ dirruns, doneName ];
   
               // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
               if ( xml ) {
                   while ( (elem = elem[ dir ]) ) {
                       if ( elem.nodeType === 1 || checkNonElements ) {
                           if ( matcher( elem, context, xml ) ) {
                               return true;
                           }
                       }
                   }
               } else {
                   while ( (elem = elem[ dir ]) ) {
                       if ( elem.nodeType === 1 || checkNonElements ) {
                           outerCache = elem[ expando ] || (elem[ expando ] = {});
   
                           // Support: IE <9 only
                           // Defend against cloned attroperties (jQuery gh-1709)
                           uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
   
                           if ( skip && skip === elem.nodeName.toLowerCase() ) {
                               elem = elem[ dir ] || elem;
                           } else if ( (oldCache = uniqueCache[ key ]) &&
                               oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
   
                               // Assign to newCache so results back-propagate to previous elements
                               return (newCache[ 2 ] = oldCache[ 2 ]);
                           } else {
                               // Reuse newcache so results back-propagate to previous elements
                               uniqueCache[ key ] = newCache;
   
                               // A match means we're done; a fail means we have to keep checking
                               if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
                                   return true;
                               }
                           }
                       }
                   }
               }
               return false;
           };
   }
   
   function elementMatcher( matchers ) {
       return matchers.length > 1 ?
           function( elem, context, xml ) {
               var i = matchers.length;
               while ( i-- ) {
                   if ( !matchers[i]( elem, context, xml ) ) {
                       return false;
                   }
               }
               return true;
           } :
           matchers[0];
   }
   
   function multipleContexts( selector, contexts, results ) {
       var i = 0,
           len = contexts.length;
       for ( ; i < len; i++ ) {
           Sizzle( selector, contexts[i], results );
       }
       return results;
   }
   
   function condense( unmatched, map, filter, context, xml ) {
       var elem,
           newUnmatched = [],
           i = 0,
           len = unmatched.length,
           mapped = map != null;
   
       for ( ; i < len; i++ ) {
           if ( (elem = unmatched[i]) ) {
               if ( !filter || filter( elem, context, xml ) ) {
                   newUnmatched.push( elem );
                   if ( mapped ) {
                       map.push( i );
                   }
               }
           }
       }
   
       return newUnmatched;
   }
   
   function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
       if ( postFilter && !postFilter[ expando ] ) {
           postFilter = setMatcher( postFilter );
       }
       if ( postFinder && !postFinder[ expando ] ) {
           postFinder = setMatcher( postFinder, postSelector );
       }
       return markFunction(function( seed, results, context, xml ) {
           var temp, i, elem,
               preMap = [],
               postMap = [],
               preexisting = results.length,
   
               // Get initial elements from seed or context
               elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
   
               // Prefilter to get matcher input, preserving a map for seed-results synchronization
               matcherIn = preFilter && ( seed || !selector ) ?
                   condense( elems, preMap, preFilter, context, xml ) :
                   elems,
   
               matcherOut = matcher ?
                   // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
                   postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
   
                       // ...intermediate processing is necessary
                       [] :
   
                       // ...otherwise use results directly
                       results :
                   matcherIn;
   
           // Find primary matches
           if ( matcher ) {
               matcher( matcherIn, matcherOut, context, xml );
           }
   
           // Apply postFilter
           if ( postFilter ) {
               temp = condense( matcherOut, postMap );
               postFilter( temp, [], context, xml );
   
               // Un-match failing elements by moving them back to matcherIn
               i = temp.length;
               while ( i-- ) {
                   if ( (elem = temp[i]) ) {
                       matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
                   }
               }
           }
   
           if ( seed ) {
               if ( postFinder || preFilter ) {
                   if ( postFinder ) {
                       // Get the final matcherOut by condensing this intermediate into postFinder contexts
                       temp = [];
                       i = matcherOut.length;
                       while ( i-- ) {
                           if ( (elem = matcherOut[i]) ) {
                               // Restore matcherIn since elem is not yet a final match
                               temp.push( (matcherIn[i] = elem) );
                           }
                       }
                       postFinder( null, (matcherOut = []), temp, xml );
                   }
   
                   // Move matched elements from seed to results to keep them synchronized
                   i = matcherOut.length;
                   while ( i-- ) {
                       if ( (elem = matcherOut[i]) &&
                           (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
   
                           seed[temp] = !(results[temp] = elem);
                       }
                   }
               }
   
           // Add elements to results, through postFinder if defined
           } else {
               matcherOut = condense(
                   matcherOut === results ?
                       matcherOut.splice( preexisting, matcherOut.length ) :
                       matcherOut
               );
               if ( postFinder ) {
                   postFinder( null, results, matcherOut, xml );
               } else {
                   push.apply( results, matcherOut );
               }
           }
       });
   }
   
   function matcherFromTokens( tokens ) {
       var checkContext, matcher, j,
           len = tokens.length,
           leadingRelative = Expr.relative[ tokens[0].type ],
           implicitRelative = leadingRelative || Expr.relative[" "],
           i = leadingRelative ? 1 : 0,
   
           // The foundational matcher ensures that elements are reachable from top-level context(s)
           matchContext = addCombinator( function( elem ) {
               return elem === checkContext;
           }, implicitRelative, true ),
           matchAnyContext = addCombinator( function( elem ) {
               return indexOf( checkContext, elem ) > -1;
           }, implicitRelative, true ),
           matchers = [ function( elem, context, xml ) {
               var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
                   (checkContext = context).nodeType ?
                       matchContext( elem, context, xml ) :
                       matchAnyContext( elem, context, xml ) );
               // Avoid hanging onto element (issue #299)
               checkContext = null;
               return ret;
           } ];
   
       for ( ; i < len; i++ ) {
           if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
               matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
           } else {
               matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
   
               // Return special upon seeing a positional matcher
               if ( matcher[ expando ] ) {
                   // Find the next relative operator (if any) for proper handling
                   j = ++i;
                   for ( ; j < len; j++ ) {
                       if ( Expr.relative[ tokens[j].type ] ) {
                           break;
                       }
                   }
                   return setMatcher(
                       i > 1 && elementMatcher( matchers ),
                       i > 1 && toSelector(
                           // If the preceding token was a descendant combinator, insert an implicit any-element `*`
                           tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
                       ).replace( rtrim, "$1" ),
                       matcher,
                       i < j && matcherFromTokens( tokens.slice( i, j ) ),
                       j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
                       j < len && toSelector( tokens )
                   );
               }
               matchers.push( matcher );
           }
       }
   
       return elementMatcher( matchers );
   }
   
   function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
       var bySet = setMatchers.length > 0,
           byElement = elementMatchers.length > 0,
           superMatcher = function( seed, context, xml, results, outermost ) {
               var elem, j, matcher,
                   matchedCount = 0,
                   i = "0",
                   unmatched = seed && [],
                   setMatched = [],
                   contextBackup = outermostContext,
                   // We must always have either seed elements or outermost context
                   elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
                   // Use integer dirruns iff this is the outermost matcher
                   dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
                   len = elems.length;
   
               if ( outermost ) {
                   outermostContext = context === document || context || outermost;
               }
   
               // Add elements passing elementMatchers directly to results
               // Support: IE<9, Safari
               // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
               for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
                   if ( byElement && elem ) {
                       j = 0;
                       if ( !context && elem.ownerDocument !== document ) {
                           setDocument( elem );
                           xml = !documentIsHTML;
                       }
                       while ( (matcher = elementMatchers[j++]) ) {
                           if ( matcher( elem, context || document, xml) ) {
                               results.push( elem );
                               break;
                           }
                       }
                       if ( outermost ) {
                           dirruns = dirrunsUnique;
                       }
                   }
   
                   // Track unmatched elements for set filters
                   if ( bySet ) {
                       // They will have gone through all possible matchers
                       if ( (elem = !matcher && elem) ) {
                           matchedCount--;
                       }
   
                       // Lengthen the array for every element, matched or not
                       if ( seed ) {
                           unmatched.push( elem );
                       }
                   }
               }
   
               // `i` is now the count of elements visited above, and adding it to `matchedCount`
               // makes the latter nonnegative.
               matchedCount += i;
   
               // Apply set filters to unmatched elements
               // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
               // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
               // no element matchers and no seed.
               // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
               // case, which will result in a "00" `matchedCount` that differs from `i` but is also
               // numerically zero.
               if ( bySet && i !== matchedCount ) {
                   j = 0;
                   while ( (matcher = setMatchers[j++]) ) {
                       matcher( unmatched, setMatched, context, xml );
                   }
   
                   if ( seed ) {
                       // Reintegrate element matches to eliminate the need for sorting
                       if ( matchedCount > 0 ) {
                           while ( i-- ) {
                               if ( !(unmatched[i] || setMatched[i]) ) {
                                   setMatched[i] = pop.call( results );
                               }
                           }
                       }
   
                       // Discard index placeholder values to get only actual matches
                       setMatched = condense( setMatched );
                   }
   
                   // Add matches to results
                   push.apply( results, setMatched );
   
                   // Seedless set matches succeeding multiple successful matchers stipulate sorting
                   if ( outermost && !seed && setMatched.length > 0 &&
                       ( matchedCount + setMatchers.length ) > 1 ) {
   
                       Sizzle.uniqueSort( results );
                   }
               }
   
               // Override manipulation of globals by nested matchers
               if ( outermost ) {
                   dirruns = dirrunsUnique;
                   outermostContext = contextBackup;
               }
   
               return unmatched;
           };
   
       return bySet ?
           markFunction( superMatcher ) :
           superMatcher;
   }
   
   compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
       var i,
           setMatchers = [],
           elementMatchers = [],
           cached = compilerCache[ selector + " " ];
   
       if ( !cached ) {
           // Generate a function of recursive functions that can be used to check each element
           if ( !match ) {
               match = tokenize( selector );
           }
           i = match.length;
           while ( i-- ) {
               cached = matcherFromTokens( match[i] );
               if ( cached[ expando ] ) {
                   setMatchers.push( cached );
               } else {
                   elementMatchers.push( cached );
               }
           }
   
           // Cache the compiled function
           cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
   
           // Save selector and tokenization
           cached.selector = selector;
       }
       return cached;
   };
   
   /**
    * A low-level selection function that works with Sizzle's compiled
    *  selector functions
    * @param {String|Function} selector A selector or a pre-compiled
    *  selector function built with Sizzle.compile
    * @param {Element} context
    * @param {Array} [results]
    * @param {Array} [seed] A set of elements to match against
    */
   select = Sizzle.select = function( selector, context, results, seed ) {
       var i, tokens, token, type, find,
           compiled = typeof selector === "function" && selector,
           match = !seed && tokenize( (selector = compiled.selector || selector) );
   
       results = results || [];
   
       // Try to minimize operations if there is only one selector in the list and no seed
       // (the latter of which guarantees us context)
       if ( match.length === 1 ) {
   
           // Reduce context if the leading compound selector is an ID
           tokens = match[0] = match[0].slice( 0 );
           if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
                   context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
   
               context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
               if ( !context ) {
                   return results;
   
               // Precompiled matchers will still verify ancestry, so step up a level
               } else if ( compiled ) {
                   context = context.parentNode;
               }
   
               selector = selector.slice( tokens.shift().value.length );
           }
   
           // Fetch a seed set for right-to-left matching
           i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
           while ( i-- ) {
               token = tokens[i];
   
               // Abort if we hit a combinator
               if ( Expr.relative[ (type = token.type) ] ) {
                   break;
               }
               if ( (find = Expr.find[ type ]) ) {
                   // Search, expanding context for leading sibling combinators
                   if ( (seed = find(
                       token.matches[0].replace( runescape, funescape ),
                       rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
                   )) ) {
   
                       // If seed is empty or no tokens remain, we can return early
                       tokens.splice( i, 1 );
                       selector = seed.length && toSelector( tokens );
                       if ( !selector ) {
                           push.apply( results, seed );
                           return results;
                       }
   
                       break;
                   }
               }
           }
       }
   
       // Compile and execute a filtering function if one is not provided
       // Provide `match` to avoid retokenization if we modified the selector above
       ( compiled || compile( selector, match ) )(
           seed,
           context,
           !documentIsHTML,
           results,
           !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
       );
       return results;
   };
   
   // One-time assignments
   
   // Sort stability
   support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
   
   // Support: Chrome 14-35+
   // Always assume duplicates if they aren't passed to the comparison function
   support.detectDuplicates = !!hasDuplicate;
   
   // Initialize against the default document
   setDocument();
   
   // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
   // Detached nodes confoundingly follow *each other*
   support.sortDetached = assert(function( el ) {
       // Should return 1, but returns 4 (following)
       return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
   });
   
   // Support: IE<8
   // Prevent attribute/property "interpolation"
   // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
   if ( !assert(function( el ) {
       el.innerHTML = "<a href='#'></a>";
       return el.firstChild.getAttribute("href") === "#" ;
   }) ) {
       addHandle( "type|href|height|width", function( elem, name, isXML ) {
           if ( !isXML ) {
               return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
           }
       });
   }
   
   // Support: IE<9
   // Use defaultValue in place of getAttribute("value")
   if ( !support.attributes || !assert(function( el ) {
       el.innerHTML = "<input/>";
       el.firstChild.setAttribute( "value", "" );
       return el.firstChild.getAttribute( "value" ) === "";
   }) ) {
       addHandle( "value", function( elem, name, isXML ) {
           if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
               return elem.defaultValue;
           }
       });
   }
   
   // Support: IE<9
   // Use getAttributeNode to fetch booleans when getAttribute lies
   if ( !assert(function( el ) {
       return el.getAttribute("disabled") == null;
   }) ) {
       addHandle( booleans, function( elem, name, isXML ) {
           var val;
           if ( !isXML ) {
               return elem[ name ] === true ? name.toLowerCase() :
                       (val = elem.getAttributeNode( name )) && val.specified ?
                       val.value :
                   null;
           }
       });
   }
   
   return Sizzle;
   
   })( window );
   
   
   
   jQuery.find = Sizzle;
   jQuery.expr = Sizzle.selectors;
   
   // Deprecated
   jQuery.expr[ ":" ] = jQuery.expr.pseudos;
   jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
   jQuery.text = Sizzle.getText;
   jQuery.isXMLDoc = Sizzle.isXML;
   jQuery.contains = Sizzle.contains;
   jQuery.escapeSelector = Sizzle.escape;
   
   
   
   
   var dir = function( elem, dir, until ) {
       var matched = [],
           truncate = until !== undefined;
   
       while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
           if ( elem.nodeType === 1 ) {
               if ( truncate && jQuery( elem ).is( until ) ) {
                   break;
               }
               matched.push( elem );
           }
       }
       return matched;
   };
   
   
   var siblings = function( n, elem ) {
       var matched = [];
   
       for ( ; n; n = n.nextSibling ) {
           if ( n.nodeType === 1 && n !== elem ) {
               matched.push( n );
           }
       }
   
       return matched;
   };
   
   
   var rneedsContext = jQuery.expr.match.needsContext;
   
   
   
   function nodeName( elem, name ) {
   
     return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
   
   };
   var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
   
   
   
   var risSimple = /^.[^:#\[\.,]*$/;
   
   // Implement the identical functionality for filter and not
   function winnow( elements, qualifier, not ) {
       if ( jQuery.isFunction( qualifier ) ) {
           return jQuery.grep( elements, function( elem, i ) {
               return !!qualifier.call( elem, i, elem ) !== not;
           } );
       }
   
       // Single element
       if ( qualifier.nodeType ) {
           return jQuery.grep( elements, function( elem ) {
               return ( elem === qualifier ) !== not;
           } );
       }
   
       // Arraylike of elements (jQuery, arguments, Array)
       if ( typeof qualifier !== "string" ) {
           return jQuery.grep( elements, function( elem ) {
               return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
           } );
       }
   
       // Simple selector that can be filtered directly, removing non-Elements
       if ( risSimple.test( qualifier ) ) {
           return jQuery.filter( qualifier, elements, not );
       }
   
       // Complex selector, compare the two sets, removing non-Elements
       qualifier = jQuery.filter( qualifier, elements );
       return jQuery.grep( elements, function( elem ) {
           return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
       } );
   }
   
   jQuery.filter = function( expr, elems, not ) {
       var elem = elems[ 0 ];
   
       if ( not ) {
           expr = ":not(" + expr + ")";
       }
   
       if ( elems.length === 1 && elem.nodeType === 1 ) {
           return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
       }
   
       return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
           return elem.nodeType === 1;
       } ) );
   };
   
   jQuery.fn.extend( {
       find: function( selector ) {
           var i, ret,
               len = this.length,
               self = this;
   
           if ( typeof selector !== "string" ) {
               return this.pushStack( jQuery( selector ).filter( function() {
                   for ( i = 0; i < len; i++ ) {
                       if ( jQuery.contains( self[ i ], this ) ) {
                           return true;
                       }
                   }
               } ) );
           }
   
           ret = this.pushStack( [] );
   
           for ( i = 0; i < len; i++ ) {
               jQuery.find( selector, self[ i ], ret );
           }
   
           return len > 1 ? jQuery.uniqueSort( ret ) : ret;
       },
       filter: function( selector ) {
           return this.pushStack( winnow( this, selector || [], false ) );
       },
       not: function( selector ) {
           return this.pushStack( winnow( this, selector || [], true ) );
       },
       is: function( selector ) {
           return !!winnow(
               this,
   
               // If this is a positional/relative selector, check membership in the returned set
               // so $("p:first").is("p:last") won't return true for a doc with two "p".
               typeof selector === "string" && rneedsContext.test( selector ) ?
                   jQuery( selector ) :
                   selector || [],
               false
           ).length;
       }
   } );
   
   
   // Initialize a jQuery object
   
   
   // A central reference to the root jQuery(document)
   var rootjQuery,
   
       // A simple way to check for HTML strings
       // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
       // Strict HTML recognition (#11290: must start with <)
       // Shortcut simple #id case for speed
       rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
   
       init = jQuery.fn.init = function( selector, context, root ) {
           var match, elem;
   
           // HANDLE: $(""), $(null), $(undefined), $(false)
           if ( !selector ) {
               return this;
           }
   
           // Method init() accepts an alternate rootjQuery
           // so migrate can support jQuery.sub (gh-2101)
           root = root || rootjQuery;
   
           // Handle HTML strings
           if ( typeof selector === "string" ) {
               if ( selector[ 0 ] === "<" &&
                   selector[ selector.length - 1 ] === ">" &&
                   selector.length >= 3 ) {
   
                   // Assume that strings that start and end with <> are HTML and skip the regex check
                   match = [ null, selector, null ];
   
               } else {
                   match = rquickExpr.exec( selector );
               }
   
               // Match html or make sure no context is specified for #id
               if ( match && ( match[ 1 ] || !context ) ) {
   
                   // HANDLE: $(html) -> $(array)
                   if ( match[ 1 ] ) {
                       context = context instanceof jQuery ? context[ 0 ] : context;
   
                       // Option to run scripts is true for back-compat
                       // Intentionally let the error be thrown if parseHTML is not present
                       jQuery.merge( this, jQuery.parseHTML(
                           match[ 1 ],
                           context && context.nodeType ? context.ownerDocument || context : document,
                           true
                       ) );
   
                       // HANDLE: $(html, props)
                       if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
                           for ( match in context ) {
   
                               // Properties of context are called as methods if possible
                               if ( jQuery.isFunction( this[ match ] ) ) {
                                   this[ match ]( context[ match ] );
   
                               // ...and otherwise set as attributes
                               } else {
                                   this.attr( match, context[ match ] );
                               }
                           }
                       }
   
                       return this;
   
                   // HANDLE: $(#id)
                   } else {
                       elem = document.getElementById( match[ 2 ] );
   
                       if ( elem ) {
   
                           // Inject the element directly into the jQuery object
                           this[ 0 ] = elem;
                           this.length = 1;
                       }
                       return this;
                   }
   
               // HANDLE: $(expr, $(...))
               } else if ( !context || context.jquery ) {
                   return ( context || root ).find( selector );
   
               // HANDLE: $(expr, context)
               // (which is just equivalent to: $(context).find(expr)
               } else {
                   return this.constructor( context ).find( selector );
               }
   
           // HANDLE: $(DOMElement)
           } else if ( selector.nodeType ) {
               this[ 0 ] = selector;
               this.length = 1;
               return this;
   
           // HANDLE: $(function)
           // Shortcut for document ready
           } else if ( jQuery.isFunction( selector ) ) {
               return root.ready !== undefined ?
                   root.ready( selector ) :
   
                   // Execute immediately if ready is not present
                   selector( jQuery );
           }
   
           return jQuery.makeArray( selector, this );
       };
   
   // Give the init function the jQuery prototype for later instantiation
   init.prototype = jQuery.fn;
   
   // Initialize central reference
   rootjQuery = jQuery( document );
   
   
   var rparentsprev = /^(?:parents|prev(?:Until|All))/,
   
       // Methods guaranteed to produce a unique set when starting from a unique set
       guaranteedUnique = {
           children: true,
           contents: true,
           next: true,
           prev: true
       };
   
   jQuery.fn.extend( {
       has: function( target ) {
           var targets = jQuery( target, this ),
               l = targets.length;
   
           return this.filter( function() {
               var i = 0;
               for ( ; i < l; i++ ) {
                   if ( jQuery.contains( this, targets[ i ] ) ) {
                       return true;
                   }
               }
           } );
       },
   
       closest: function( selectors, context ) {
           var cur,
               i = 0,
               l = this.length,
               matched = [],
               targets = typeof selectors !== "string" && jQuery( selectors );
   
           // Positional selectors never match, since there's no _selection_ context
           if ( !rneedsContext.test( selectors ) ) {
               for ( ; i < l; i++ ) {
                   for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
   
                       // Always skip document fragments
                       if ( cur.nodeType < 11 && ( targets ?
                           targets.index( cur ) > -1 :
   
                           // Don't pass non-elements to Sizzle
                           cur.nodeType === 1 &&
                               jQuery.find.matchesSelector( cur, selectors ) ) ) {
   
                           matched.push( cur );
                           break;
                       }
                   }
               }
           }
   
           return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
       },
   
       // Determine the position of an element within the set
       index: function( elem ) {
   
           // No argument, return index in parent
           if ( !elem ) {
               return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
           }
   
           // Index in selector
           if ( typeof elem === "string" ) {
               return indexOf.call( jQuery( elem ), this[ 0 ] );
           }
   
           // Locate the position of the desired element
           return indexOf.call( this,
   
               // If it receives a jQuery object, the first element is used
               elem.jquery ? elem[ 0 ] : elem
           );
       },
   
       add: function( selector, context ) {
           return this.pushStack(
               jQuery.uniqueSort(
                   jQuery.merge( this.get(), jQuery( selector, context ) )
               )
           );
       },
   
       addBack: function( selector ) {
           return this.add( selector == null ?
               this.prevObject : this.prevObject.filter( selector )
           );
       }
   } );
   
   function sibling( cur, dir ) {
       while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
       return cur;
   }
   
   jQuery.each( {
       parent: function( elem ) {
           var parent = elem.parentNode;
           return parent && parent.nodeType !== 11 ? parent : null;
       },
       parents: function( elem ) {
           return dir( elem, "parentNode" );
       },
       parentsUntil: function( elem, i, until ) {
           return dir( elem, "parentNode", until );
       },
       next: function( elem ) {
           return sibling( elem, "nextSibling" );
       },
       prev: function( elem ) {
           return sibling( elem, "previousSibling" );
       },
       nextAll: function( elem ) {
           return dir( elem, "nextSibling" );
       },
       prevAll: function( elem ) {
           return dir( elem, "previousSibling" );
       },
       nextUntil: function( elem, i, until ) {
           return dir( elem, "nextSibling", until );
       },
       prevUntil: function( elem, i, until ) {
           return dir( elem, "previousSibling", until );
       },
       siblings: function( elem ) {
           return siblings( ( elem.parentNode || {} ).firstChild, elem );
       },
       children: function( elem ) {
           return siblings( elem.firstChild );
       },
       contents: function( elem ) {
           if ( nodeName( elem, "iframe" ) ) {
               return elem.contentDocument;
           }
   
           // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
           // Treat the template element as a regular one in browsers that
           // don't support it.
           if ( nodeName( elem, "template" ) ) {
               elem = elem.content || elem;
           }
   
           return jQuery.merge( [], elem.childNodes );
       }
   }, function( name, fn ) {
       jQuery.fn[ name ] = function( until, selector ) {
           var matched = jQuery.map( this, fn, until );
   
           if ( name.slice( -5 ) !== "Until" ) {
               selector = until;
           }
   
           if ( selector && typeof selector === "string" ) {
               matched = jQuery.filter( selector, matched );
           }
   
           if ( this.length > 1 ) {
   
               // Remove duplicates
               if ( !guaranteedUnique[ name ] ) {
                   jQuery.uniqueSort( matched );
               }
   
               // Reverse order for parents* and prev-derivatives
               if ( rparentsprev.test( name ) ) {
                   matched.reverse();
               }
           }
   
           return this.pushStack( matched );
       };
   } );
   var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
   
   
   
   // Convert String-formatted options into Object-formatted ones
   function createOptions( options ) {
       var object = {};
       jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
           object[ flag ] = true;
       } );
       return object;
   }
   
   /*
    * Create a callback list using the following parameters:
    *
    *	options: an optional list of space-separated options that will change how
    *			the callback list behaves or a more traditional option object
    *
    * By default a callback list will act like an event callback list and can be
    * "fired" multiple times.
    *
    * Possible options:
    *
    *	once:			will ensure the callback list can only be fired once (like a Deferred)
    *
    *	memory:			will keep track of previous values and will call any callback added
    *					after the list has been fired right away with the latest "memorized"
    *					values (like a Deferred)
    *
    *	unique:			will ensure a callback can only be added once (no duplicate in the list)
    *
    *	stopOnFalse:	interrupt callings when a callback returns false
    *
    */
   jQuery.Callbacks = function( options ) {
   
       // Convert options from String-formatted to Object-formatted if needed
       // (we check in cache first)
       options = typeof options === "string" ?
           createOptions( options ) :
           jQuery.extend( {}, options );
   
       var // Flag to know if list is currently firing
           firing,
   
           // Last fire value for non-forgettable lists
           memory,
   
           // Flag to know if list was already fired
           fired,
   
           // Flag to prevent firing
           locked,
   
           // Actual callback list
           list = [],
   
           // Queue of execution data for repeatable lists
           queue = [],
   
           // Index of currently firing callback (modified by add/remove as needed)
           firingIndex = -1,
   
           // Fire callbacks
           fire = function() {
   
               // Enforce single-firing
               locked = locked || options.once;
   
               // Execute callbacks for all pending executions,
               // respecting firingIndex overrides and runtime changes
               fired = firing = true;
               for ( ; queue.length; firingIndex = -1 ) {
                   memory = queue.shift();
                   while ( ++firingIndex < list.length ) {
   
                       // Run callback and check for early termination
                       if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
                           options.stopOnFalse ) {
   
                           // Jump to end and forget the data so .add doesn't re-fire
                           firingIndex = list.length;
                           memory = false;
                       }
                   }
               }
   
               // Forget the data if we're done with it
               if ( !options.memory ) {
                   memory = false;
               }
   
               firing = false;
   
               // Clean up if we're done firing for good
               if ( locked ) {
   
                   // Keep an empty list if we have data for future add calls
                   if ( memory ) {
                       list = [];
   
                   // Otherwise, this object is spent
                   } else {
                       list = "";
                   }
               }
           },
   
           // Actual Callbacks object
           self = {
   
               // Add a callback or a collection of callbacks to the list
               add: function() {
                   if ( list ) {
   
                       // If we have memory from a past run, we should fire after adding
                       if ( memory && !firing ) {
                           firingIndex = list.length - 1;
                           queue.push( memory );
                       }
   
                       ( function add( args ) {
                           jQuery.each( args, function( _, arg ) {
                               if ( jQuery.isFunction( arg ) ) {
                                   if ( !options.unique || !self.has( arg ) ) {
                                       list.push( arg );
                                   }
                               } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
   
                                   // Inspect recursively
                                   add( arg );
                               }
                           } );
                       } )( arguments );
   
                       if ( memory && !firing ) {
                           fire();
                       }
                   }
                   return this;
               },
   
               // Remove a callback from the list
               remove: function() {
                   jQuery.each( arguments, function( _, arg ) {
                       var index;
                       while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
                           list.splice( index, 1 );
   
                           // Handle firing indexes
                           if ( index <= firingIndex ) {
                               firingIndex--;
                           }
                       }
                   } );
                   return this;
               },
   
               // Check if a given callback is in the list.
               // If no argument is given, return whether or not list has callbacks attached.
               has: function( fn ) {
                   return fn ?
                       jQuery.inArray( fn, list ) > -1 :
                       list.length > 0;
               },
   
               // Remove all callbacks from the list
               empty: function() {
                   if ( list ) {
                       list = [];
                   }
                   return this;
               },
   
               // Disable .fire and .add
               // Abort any current/pending executions
               // Clear all callbacks and values
               disable: function() {
                   locked = queue = [];
                   list = memory = "";
                   return this;
               },
               disabled: function() {
                   return !list;
               },
   
               // Disable .fire
               // Also disable .add unless we have memory (since it would have no effect)
               // Abort any pending executions
               lock: function() {
                   locked = queue = [];
                   if ( !memory && !firing ) {
                       list = memory = "";
                   }
                   return this;
               },
               locked: function() {
                   return !!locked;
               },
   
               // Call all callbacks with the given context and arguments
               fireWith: function( context, args ) {
                   if ( !locked ) {
                       args = args || [];
                       args = [ context, args.slice ? args.slice() : args ];
                       queue.push( args );
                       if ( !firing ) {
                           fire();
                       }
                   }
                   return this;
               },
   
               // Call all the callbacks with the given arguments
               fire: function() {
                   self.fireWith( this, arguments );
                   return this;
               },
   
               // To know if the callbacks have already been called at least once
               fired: function() {
                   return !!fired;
               }
           };
   
       return self;
   };
   
   
   function Identity( v ) {
       return v;
   }
   function Thrower( ex ) {
       throw ex;
   }
   
   function adoptValue( value, resolve, reject, noValue ) {
       var method;
   
       try {
   
           // Check for promise aspect first to privilege synchronous behavior
           if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
               method.call( value ).done( resolve ).fail( reject );
   
           // Other thenables
           } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
               method.call( value, resolve, reject );
   
           // Other non-thenables
           } else {
   
               // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
               // * false: [ value ].slice( 0 ) => resolve( value )
               // * true: [ value ].slice( 1 ) => resolve()
               resolve.apply( undefined, [ value ].slice( noValue ) );
           }
   
       // For Promises/A+, convert exceptions into rejections
       // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
       // Deferred#then to conditionally suppress rejection.
       } catch ( value ) {
   
           // Support: Android 4.0 only
           // Strict mode functions invoked without .call/.apply get global-object context
           reject.apply( undefined, [ value ] );
       }
   }
   
   jQuery.extend( {
   
       Deferred: function( func ) {
           var tuples = [
   
                   // action, add listener, callbacks,
                   // ... .then handlers, argument index, [final state]
                   [ "notify", "progress", jQuery.Callbacks( "memory" ),
                       jQuery.Callbacks( "memory" ), 2 ],
                   [ "resolve", "done", jQuery.Callbacks( "once memory" ),
                       jQuery.Callbacks( "once memory" ), 0, "resolved" ],
                   [ "reject", "fail", jQuery.Callbacks( "once memory" ),
                       jQuery.Callbacks( "once memory" ), 1, "rejected" ]
               ],
               state = "pending",
               promise = {
                   state: function() {
                       return state;
                   },
                   always: function() {
                       deferred.done( arguments ).fail( arguments );
                       return this;
                   },
                   "catch": function( fn ) {
                       return promise.then( null, fn );
                   },
   
                   // Keep pipe for back-compat
                   pipe: function( /* fnDone, fnFail, fnProgress */ ) {
                       var fns = arguments;
   
                       return jQuery.Deferred( function( newDefer ) {
                           jQuery.each( tuples, function( i, tuple ) {
   
                               // Map tuples (progress, done, fail) to arguments (done, fail, progress)
                               var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
   
                               // deferred.progress(function() { bind to newDefer or newDefer.notify })
                               // deferred.done(function() { bind to newDefer or newDefer.resolve })
                               // deferred.fail(function() { bind to newDefer or newDefer.reject })
                               deferred[ tuple[ 1 ] ]( function() {
                                   var returned = fn && fn.apply( this, arguments );
                                   if ( returned && jQuery.isFunction( returned.promise ) ) {
                                       returned.promise()
                                           .progress( newDefer.notify )
                                           .done( newDefer.resolve )
                                           .fail( newDefer.reject );
                                   } else {
                                       newDefer[ tuple[ 0 ] + "With" ](
                                           this,
                                           fn ? [ returned ] : arguments
                                       );
                                   }
                               } );
                           } );
                           fns = null;
                       } ).promise();
                   },
                   then: function( onFulfilled, onRejected, onProgress ) {
                       var maxDepth = 0;
                       function resolve( depth, deferred, handler, special ) {
                           return function() {
                               var that = this,
                                   args = arguments,
                                   mightThrow = function() {
                                       var returned, then;
   
                                       // Support: Promises/A+ section 2.3.3.3.3
                                       // https://promisesaplus.com/#point-59
                                       // Ignore double-resolution attempts
                                       if ( depth < maxDepth ) {
                                           return;
                                       }
   
                                       returned = handler.apply( that, args );
   
                                       // Support: Promises/A+ section 2.3.1
                                       // https://promisesaplus.com/#point-48
                                       if ( returned === deferred.promise() ) {
                                           throw new TypeError( "Thenable self-resolution" );
                                       }
   
                                       // Support: Promises/A+ sections 2.3.3.1, 3.5
                                       // https://promisesaplus.com/#point-54
                                       // https://promisesaplus.com/#point-75
                                       // Retrieve `then` only once
                                       then = returned &&
   
                                           // Support: Promises/A+ section 2.3.4
                                           // https://promisesaplus.com/#point-64
                                           // Only check objects and functions for thenability
                                           ( typeof returned === "object" ||
                                               typeof returned === "function" ) &&
                                           returned.then;
   
                                       // Handle a returned thenable
                                       if ( jQuery.isFunction( then ) ) {
   
                                           // Special processors (notify) just wait for resolution
                                           if ( special ) {
                                               then.call(
                                                   returned,
                                                   resolve( maxDepth, deferred, Identity, special ),
                                                   resolve( maxDepth, deferred, Thrower, special )
                                               );
   
                                           // Normal processors (resolve) also hook into progress
                                           } else {
   
                                               // ...and disregard older resolution values
                                               maxDepth++;
   
                                               then.call(
                                                   returned,
                                                   resolve( maxDepth, deferred, Identity, special ),
                                                   resolve( maxDepth, deferred, Thrower, special ),
                                                   resolve( maxDepth, deferred, Identity,
                                                       deferred.notifyWith )
                                               );
                                           }
   
                                       // Handle all other returned values
                                       } else {
   
                                           // Only substitute handlers pass on context
                                           // and multiple values (non-spec behavior)
                                           if ( handler !== Identity ) {
                                               that = undefined;
                                               args = [ returned ];
                                           }
   
                                           // Process the value(s)
                                           // Default process is resolve
                                           ( special || deferred.resolveWith )( that, args );
                                       }
                                   },
   
                                   // Only normal processors (resolve) catch and reject exceptions
                                   process = special ?
                                       mightThrow :
                                       function() {
                                           try {
                                               mightThrow();
                                           } catch ( e ) {
   
                                               if ( jQuery.Deferred.exceptionHook ) {
                                                   jQuery.Deferred.exceptionHook( e,
                                                       process.stackTrace );
                                               }
   
                                               // Support: Promises/A+ section 2.3.3.3.4.1
                                               // https://promisesaplus.com/#point-61
                                               // Ignore post-resolution exceptions
                                               if ( depth + 1 >= maxDepth ) {
   
                                                   // Only substitute handlers pass on context
                                                   // and multiple values (non-spec behavior)
                                                   if ( handler !== Thrower ) {
                                                       that = undefined;
                                                       args = [ e ];
                                                   }
   
                                                   deferred.rejectWith( that, args );
                                               }
                                           }
                                       };
   
                               // Support: Promises/A+ section 2.3.3.3.1
                               // https://promisesaplus.com/#point-57
                               // Re-resolve promises immediately to dodge false rejection from
                               // subsequent errors
                               if ( depth ) {
                                   process();
                               } else {
   
                                   // Call an optional hook to record the stack, in case of exception
                                   // since it's otherwise lost when execution goes async
                                   if ( jQuery.Deferred.getStackHook ) {
                                       process.stackTrace = jQuery.Deferred.getStackHook();
                                   }
                                   window.setTimeout( process );
                               }
                           };
                       }
   
                       return jQuery.Deferred( function( newDefer ) {
   
                           // progress_handlers.add( ... )
                           tuples[ 0 ][ 3 ].add(
                               resolve(
                                   0,
                                   newDefer,
                                   jQuery.isFunction( onProgress ) ?
                                       onProgress :
                                       Identity,
                                   newDefer.notifyWith
                               )
                           );
   
                           // fulfilled_handlers.add( ... )
                           tuples[ 1 ][ 3 ].add(
                               resolve(
                                   0,
                                   newDefer,
                                   jQuery.isFunction( onFulfilled ) ?
                                       onFulfilled :
                                       Identity
                               )
                           );
   
                           // rejected_handlers.add( ... )
                           tuples[ 2 ][ 3 ].add(
                               resolve(
                                   0,
                                   newDefer,
                                   jQuery.isFunction( onRejected ) ?
                                       onRejected :
                                       Thrower
                               )
                           );
                       } ).promise();
                   },
   
                   // Get a promise for this deferred
                   // If obj is provided, the promise aspect is added to the object
                   promise: function( obj ) {
                       return obj != null ? jQuery.extend( obj, promise ) : promise;
                   }
               },
               deferred = {};
   
           // Add list-specific methods
           jQuery.each( tuples, function( i, tuple ) {
               var list = tuple[ 2 ],
                   stateString = tuple[ 5 ];
   
               // promise.progress = list.add
               // promise.done = list.add
               // promise.fail = list.add
               promise[ tuple[ 1 ] ] = list.add;
   
               // Handle state
               if ( stateString ) {
                   list.add(
                       function() {
   
                           // state = "resolved" (i.e., fulfilled)
                           // state = "rejected"
                           state = stateString;
                       },
   
                       // rejected_callbacks.disable
                       // fulfilled_callbacks.disable
                       tuples[ 3 - i ][ 2 ].disable,
   
                       // progress_callbacks.lock
                       tuples[ 0 ][ 2 ].lock
                   );
               }
   
               // progress_handlers.fire
               // fulfilled_handlers.fire
               // rejected_handlers.fire
               list.add( tuple[ 3 ].fire );
   
               // deferred.notify = function() { deferred.notifyWith(...) }
               // deferred.resolve = function() { deferred.resolveWith(...) }
               // deferred.reject = function() { deferred.rejectWith(...) }
               deferred[ tuple[ 0 ] ] = function() {
                   deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
                   return this;
               };
   
               // deferred.notifyWith = list.fireWith
               // deferred.resolveWith = list.fireWith
               // deferred.rejectWith = list.fireWith
               deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
           } );
   
           // Make the deferred a promise
           promise.promise( deferred );
   
           // Call given func if any
           if ( func ) {
               func.call( deferred, deferred );
           }
   
           // All done!
           return deferred;
       },
   
       // Deferred helper
       when: function( singleValue ) {
           var
   
               // count of uncompleted subordinates
               remaining = arguments.length,
   
               // count of unprocessed arguments
               i = remaining,
   
               // subordinate fulfillment data
               resolveContexts = Array( i ),
               resolveValues = slice.call( arguments ),
   
               // the master Deferred
               master = jQuery.Deferred(),
   
               // subordinate callback factory
               updateFunc = function( i ) {
                   return function( value ) {
                       resolveContexts[ i ] = this;
                       resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
                       if ( !( --remaining ) ) {
                           master.resolveWith( resolveContexts, resolveValues );
                       }
                   };
               };
   
           // Single- and empty arguments are adopted like Promise.resolve
           if ( remaining <= 1 ) {
               adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
                   !remaining );
   
               // Use .then() to unwrap secondary thenables (cf. gh-3000)
               if ( master.state() === "pending" ||
                   jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
   
                   return master.then();
               }
           }
   
           // Multiple arguments are aggregated like Promise.all array elements
           while ( i-- ) {
               adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
           }
   
           return master.promise();
       }
   } );
   
   
   // These usually indicate a programmer mistake during development,
   // warn about them ASAP rather than swallowing them by default.
   var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
   
   jQuery.Deferred.exceptionHook = function( error, stack ) {
   
       // Support: IE 8 - 9 only
       // Console exists when dev tools are open, which can happen at any time
       if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
           window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
       }
   };
   
   
   
   
   jQuery.readyException = function( error ) {
       window.setTimeout( function() {
           throw error;
       } );
   };
   
   
   
   
   // The deferred used on DOM ready
   var readyList = jQuery.Deferred();
   
   jQuery.fn.ready = function( fn ) {
   
       readyList
           .then( fn )
   
           // Wrap jQuery.readyException in a function so that the lookup
           // happens at the time of error handling instead of callback
           // registration.
           .catch( function( error ) {
               jQuery.readyException( error );
           } );
   
       return this;
   };
   
   jQuery.extend( {
   
       // Is the DOM ready to be used? Set to true once it occurs.
       isReady: false,
   
       // A counter to track how many items to wait for before
       // the ready event fires. See #6781
       readyWait: 1,
   
       // Handle when the DOM is ready
       ready: function( wait ) {
   
           // Abort if there are pending holds or we're already ready
           if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
               return;
           }
   
           // Remember that the DOM is ready
           jQuery.isReady = true;
   
           // If a normal DOM Ready event fired, decrement, and wait if need be
           if ( wait !== true && --jQuery.readyWait > 0 ) {
               return;
           }
   
           // If there are functions bound, to execute
           readyList.resolveWith( document, [ jQuery ] );
       }
   } );
   
   jQuery.ready.then = readyList.then;
   
   // The ready event handler and self cleanup method
   function completed() {
       document.removeEventListener( "DOMContentLoaded", completed );
       window.removeEventListener( "load", completed );
       jQuery.ready();
   }
   
   // Catch cases where $(document).ready() is called
   // after the browser event has already occurred.
   // Support: IE <=9 - 10 only
   // Older IE sometimes signals "interactive" too soon
   if ( document.readyState === "complete" ||
       ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
   
       // Handle it asynchronously to allow scripts the opportunity to delay ready
       window.setTimeout( jQuery.ready );
   
   } else {
   
       // Use the handy event callback
       document.addEventListener( "DOMContentLoaded", completed );
   
       // A fallback to window.onload, that will always work
       window.addEventListener( "load", completed );
   }
   
   
   
   
   // Multifunctional method to get and set values of a collection
   // The value/s can optionally be executed if it's a function
   var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
       var i = 0,
           len = elems.length,
           bulk = key == null;
   
       // Sets many values
       if ( jQuery.type( key ) === "object" ) {
           chainable = true;
           for ( i in key ) {
               access( elems, fn, i, key[ i ], true, emptyGet, raw );
           }
   
       // Sets one value
       } else if ( value !== undefined ) {
           chainable = true;
   
           if ( !jQuery.isFunction( value ) ) {
               raw = true;
           }
   
           if ( bulk ) {
   
               // Bulk operations run against the entire set
               if ( raw ) {
                   fn.call( elems, value );
                   fn = null;
   
               // ...except when executing function values
               } else {
                   bulk = fn;
                   fn = function( elem, key, value ) {
                       return bulk.call( jQuery( elem ), value );
                   };
               }
           }
   
           if ( fn ) {
               for ( ; i < len; i++ ) {
                   fn(
                       elems[ i ], key, raw ?
                       value :
                       value.call( elems[ i ], i, fn( elems[ i ], key ) )
                   );
               }
           }
       }
   
       if ( chainable ) {
           return elems;
       }
   
       // Gets
       if ( bulk ) {
           return fn.call( elems );
       }
   
       return len ? fn( elems[ 0 ], key ) : emptyGet;
   };
   var acceptData = function( owner ) {
   
       // Accepts only:
       //  - Node
       //    - Node.ELEMENT_NODE
       //    - Node.DOCUMENT_NODE
       //  - Object
       //    - Any
       return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
   };
   
   
   
   
   function Data() {
       this.expando = jQuery.expando + Data.uid++;
   }
   
   Data.uid = 1;
   
   Data.prototype = {
   
       cache: function( owner ) {
   
           // Check if the owner object already has a cache
           var value = owner[ this.expando ];
   
           // If not, create one
           if ( !value ) {
               value = {};
   
               // We can accept data for non-element nodes in modern browsers,
               // but we should not, see #8335.
               // Always return an empty object.
               if ( acceptData( owner ) ) {
   
                   // If it is a node unlikely to be stringify-ed or looped over
                   // use plain assignment
                   if ( owner.nodeType ) {
                       owner[ this.expando ] = value;
   
                   // Otherwise secure it in a non-enumerable property
                   // configurable must be true to allow the property to be
                   // deleted when data is removed
                   } else {
                       Object.defineProperty( owner, this.expando, {
                           value: value,
                           configurable: true
                       } );
                   }
               }
           }
   
           return value;
       },
       set: function( owner, data, value ) {
           var prop,
               cache = this.cache( owner );
   
           // Handle: [ owner, key, value ] args
           // Always use camelCase key (gh-2257)
           if ( typeof data === "string" ) {
               cache[ jQuery.camelCase( data ) ] = value;
   
           // Handle: [ owner, { properties } ] args
           } else {
   
               // Copy the properties one-by-one to the cache object
               for ( prop in data ) {
                   cache[ jQuery.camelCase( prop ) ] = data[ prop ];
               }
           }
           return cache;
       },
       get: function( owner, key ) {
           return key === undefined ?
               this.cache( owner ) :
   
               // Always use camelCase key (gh-2257)
               owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
       },
       access: function( owner, key, value ) {
   
           // In cases where either:
           //
           //   1. No key was specified
           //   2. A string key was specified, but no value provided
           //
           // Take the "read" path and allow the get method to determine
           // which value to return, respectively either:
           //
           //   1. The entire cache object
           //   2. The data stored at the key
           //
           if ( key === undefined ||
                   ( ( key && typeof key === "string" ) && value === undefined ) ) {
   
               return this.get( owner, key );
           }
   
           // When the key is not a string, or both a key and value
           // are specified, set or extend (existing objects) with either:
           //
           //   1. An object of properties
           //   2. A key and value
           //
           this.set( owner, key, value );
   
           // Since the "set" path can have two possible entry points
           // return the expected data based on which path was taken[*]
           return value !== undefined ? value : key;
       },
       remove: function( owner, key ) {
           var i,
               cache = owner[ this.expando ];
   
           if ( cache === undefined ) {
               return;
           }
   
           if ( key !== undefined ) {
   
               // Support array or space separated string of keys
               if ( Array.isArray( key ) ) {
   
                   // If key is an array of keys...
                   // We always set camelCase keys, so remove that.
                   key = key.map( jQuery.camelCase );
               } else {
                   key = jQuery.camelCase( key );
   
                   // If a key with the spaces exists, use it.
                   // Otherwise, create an array by matching non-whitespace
                   key = key in cache ?
                       [ key ] :
                       ( key.match( rnothtmlwhite ) || [] );
               }
   
               i = key.length;
   
               while ( i-- ) {
                   delete cache[ key[ i ] ];
               }
           }
   
           // Remove the expando if there's no more data
           if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
   
               // Support: Chrome <=35 - 45
               // Webkit & Blink performance suffers when deleting properties
               // from DOM nodes, so set to undefined instead
               // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
               if ( owner.nodeType ) {
                   owner[ this.expando ] = undefined;
               } else {
                   delete owner[ this.expando ];
               }
           }
       },
       hasData: function( owner ) {
           var cache = owner[ this.expando ];
           return cache !== undefined && !jQuery.isEmptyObject( cache );
       }
   };
   var dataPriv = new Data();
   
   var dataUser = new Data();
   
   
   
   //	Implementation Summary
   //
   //	1. Enforce API surface and semantic compatibility with 1.9.x branch
   //	2. Improve the module's maintainability by reducing the storage
   //		paths to a single mechanism.
   //	3. Use the same single mechanism to support "private" and "user" data.
   //	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
   //	5. Avoid exposing implementation details on user objects (eg. expando properties)
   //	6. Provide a clear path for implementation upgrade to WeakMap in 2014
   
   var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
       rmultiDash = /[A-Z]/g;
   
   function getData( data ) {
       if ( data === "true" ) {
           return true;
       }
   
       if ( data === "false" ) {
           return false;
       }
   
       if ( data === "null" ) {
           return null;
       }
   
       // Only convert to a number if it doesn't change the string
       if ( data === +data + "" ) {
           return +data;
       }
   
       if ( rbrace.test( data ) ) {
           return JSON.parse( data );
       }
   
       return data;
   }
   
   function dataAttr( elem, key, data ) {
       var name;
   
       // If nothing was found internally, try to fetch any
       // data from the HTML5 data-* attribute
       if ( data === undefined && elem.nodeType === 1 ) {
           name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
           data = elem.getAttribute( name );
   
           if ( typeof data === "string" ) {
               try {
                   data = getData( data );
               } catch ( e ) {}
   
               // Make sure we set the data so it isn't changed later
               dataUser.set( elem, key, data );
           } else {
               data = undefined;
           }
       }
       return data;
   }
   
   jQuery.extend( {
       hasData: function( elem ) {
           return dataUser.hasData( elem ) || dataPriv.hasData( elem );
       },
   
       data: function( elem, name, data ) {
           return dataUser.access( elem, name, data );
       },
   
       removeData: function( elem, name ) {
           dataUser.remove( elem, name );
       },
   
       // TODO: Now that all calls to _data and _removeData have been replaced
       // with direct calls to dataPriv methods, these can be deprecated.
       _data: function( elem, name, data ) {
           return dataPriv.access( elem, name, data );
       },
   
       _removeData: function( elem, name ) {
           dataPriv.remove( elem, name );
       }
   } );
   
   jQuery.fn.extend( {
       data: function( key, value ) {
           var i, name, data,
               elem = this[ 0 ],
               attrs = elem && elem.attributes;
   
           // Gets all values
           if ( key === undefined ) {
               if ( this.length ) {
                   data = dataUser.get( elem );
   
                   if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
                       i = attrs.length;
                       while ( i-- ) {
   
                           // Support: IE 11 only
                           // The attrs elements can be null (#14894)
                           if ( attrs[ i ] ) {
                               name = attrs[ i ].name;
                               if ( name.indexOf( "data-" ) === 0 ) {
                                   name = jQuery.camelCase( name.slice( 5 ) );
                                   dataAttr( elem, name, data[ name ] );
                               }
                           }
                       }
                       dataPriv.set( elem, "hasDataAttrs", true );
                   }
               }
   
               return data;
           }
   
           // Sets multiple values
           if ( typeof key === "object" ) {
               return this.each( function() {
                   dataUser.set( this, key );
               } );
           }
   
           return access( this, function( value ) {
               var data;
   
               // The calling jQuery object (element matches) is not empty
               // (and therefore has an element appears at this[ 0 ]) and the
               // `value` parameter was not undefined. An empty jQuery object
               // will result in `undefined` for elem = this[ 0 ] which will
               // throw an exception if an attempt to read a data cache is made.
               if ( elem && value === undefined ) {
   
                   // Attempt to get data from the cache
                   // The key will always be camelCased in Data
                   data = dataUser.get( elem, key );
                   if ( data !== undefined ) {
                       return data;
                   }
   
                   // Attempt to "discover" the data in
                   // HTML5 custom data-* attrs
                   data = dataAttr( elem, key );
                   if ( data !== undefined ) {
                       return data;
                   }
   
                   // We tried really hard, but the data doesn't exist.
                   return;
               }
   
               // Set the data...
               this.each( function() {
   
                   // We always store the camelCased key
                   dataUser.set( this, key, value );
               } );
           }, null, value, arguments.length > 1, null, true );
       },
   
       removeData: function( key ) {
           return this.each( function() {
               dataUser.remove( this, key );
           } );
       }
   } );
   
   
   jQuery.extend( {
       queue: function( elem, type, data ) {
           var queue;
   
           if ( elem ) {
               type = ( type || "fx" ) + "queue";
               queue = dataPriv.get( elem, type );
   
               // Speed up dequeue by getting out quickly if this is just a lookup
               if ( data ) {
                   if ( !queue || Array.isArray( data ) ) {
                       queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
                   } else {
                       queue.push( data );
                   }
               }
               return queue || [];
           }
       },
   
       dequeue: function( elem, type ) {
           type = type || "fx";
   
           var queue = jQuery.queue( elem, type ),
               startLength = queue.length,
               fn = queue.shift(),
               hooks = jQuery._queueHooks( elem, type ),
               next = function() {
                   jQuery.dequeue( elem, type );
               };
   
           // If the fx queue is dequeued, always remove the progress sentinel
           if ( fn === "inprogress" ) {
               fn = queue.shift();
               startLength--;
           }
   
           if ( fn ) {
   
               // Add a progress sentinel to prevent the fx queue from being
               // automatically dequeued
               if ( type === "fx" ) {
                   queue.unshift( "inprogress" );
               }
   
               // Clear up the last queue stop function
               delete hooks.stop;
               fn.call( elem, next, hooks );
           }
   
           if ( !startLength && hooks ) {
               hooks.empty.fire();
           }
       },
   
       // Not public - generate a queueHooks object, or return the current one
       _queueHooks: function( elem, type ) {
           var key = type + "queueHooks";
           return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
               empty: jQuery.Callbacks( "once memory" ).add( function() {
                   dataPriv.remove( elem, [ type + "queue", key ] );
               } )
           } );
       }
   } );
   
   jQuery.fn.extend( {
       queue: function( type, data ) {
           var setter = 2;
   
           if ( typeof type !== "string" ) {
               data = type;
               type = "fx";
               setter--;
           }
   
           if ( arguments.length < setter ) {
               return jQuery.queue( this[ 0 ], type );
           }
   
           return data === undefined ?
               this :
               this.each( function() {
                   var queue = jQuery.queue( this, type, data );
   
                   // Ensure a hooks for this queue
                   jQuery._queueHooks( this, type );
   
                   if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
                       jQuery.dequeue( this, type );
                   }
               } );
       },
       dequeue: function( type ) {
           return this.each( function() {
               jQuery.dequeue( this, type );
           } );
       },
       clearQueue: function( type ) {
           return this.queue( type || "fx", [] );
       },
   
       // Get a promise resolved when queues of a certain type
       // are emptied (fx is the type by default)
       promise: function( type, obj ) {
           var tmp,
               count = 1,
               defer = jQuery.Deferred(),
               elements = this,
               i = this.length,
               resolve = function() {
                   if ( !( --count ) ) {
                       defer.resolveWith( elements, [ elements ] );
                   }
               };
   
           if ( typeof type !== "string" ) {
               obj = type;
               type = undefined;
           }
           type = type || "fx";
   
           while ( i-- ) {
               tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
               if ( tmp && tmp.empty ) {
                   count++;
                   tmp.empty.add( resolve );
               }
           }
           resolve();
           return defer.promise( obj );
       }
   } );
   var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
   
   var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
   
   
   var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
   
   var isHiddenWithinTree = function( elem, el ) {
   
           // isHiddenWithinTree might be called from jQuery#filter function;
           // in that case, element will be second argument
           elem = el || elem;
   
           // Inline style trumps all
           return elem.style.display === "none" ||
               elem.style.display === "" &&
   
               // Otherwise, check computed style
               // Support: Firefox <=43 - 45
               // Disconnected elements can have computed display: none, so first confirm that elem is
               // in the document.
               jQuery.contains( elem.ownerDocument, elem ) &&
   
               jQuery.css( elem, "display" ) === "none";
       };
   
   var swap = function( elem, options, callback, args ) {
       var ret, name,
           old = {};
   
       // Remember the old values, and insert the new ones
       for ( name in options ) {
           old[ name ] = elem.style[ name ];
           elem.style[ name ] = options[ name ];
       }
   
       ret = callback.apply( elem, args || [] );
   
       // Revert the old values
       for ( name in options ) {
           elem.style[ name ] = old[ name ];
       }
   
       return ret;
   };
   
   
   
   
   function adjustCSS( elem, prop, valueParts, tween ) {
       var adjusted,
           scale = 1,
           maxIterations = 20,
           currentValue = tween ?
               function() {
                   return tween.cur();
               } :
               function() {
                   return jQuery.css( elem, prop, "" );
               },
           initial = currentValue(),
           unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
   
           // Starting value computation is required for potential unit mismatches
           initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
               rcssNum.exec( jQuery.css( elem, prop ) );
   
       if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
   
           // Trust units reported by jQuery.css
           unit = unit || initialInUnit[ 3 ];
   
           // Make sure we update the tween properties later on
           valueParts = valueParts || [];
   
           // Iteratively approximate from a nonzero starting point
           initialInUnit = +initial || 1;
   
           do {
   
               // If previous iteration zeroed out, double until we get *something*.
               // Use string for doubling so we don't accidentally see scale as unchanged below
               scale = scale || ".5";
   
               // Adjust and apply
               initialInUnit = initialInUnit / scale;
               jQuery.style( elem, prop, initialInUnit + unit );
   
           // Update scale, tolerating zero or NaN from tween.cur()
           // Break the loop if scale is unchanged or perfect, or if we've just had enough.
           } while (
               scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
           );
       }
   
       if ( valueParts ) {
           initialInUnit = +initialInUnit || +initial || 0;
   
           // Apply relative offset (+=/-=) if specified
           adjusted = valueParts[ 1 ] ?
               initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
               +valueParts[ 2 ];
           if ( tween ) {
               tween.unit = unit;
               tween.start = initialInUnit;
               tween.end = adjusted;
           }
       }
       return adjusted;
   }
   
   
   var defaultDisplayMap = {};
   
   function getDefaultDisplay( elem ) {
       var temp,
           doc = elem.ownerDocument,
           nodeName = elem.nodeName,
           display = defaultDisplayMap[ nodeName ];
   
       if ( display ) {
           return display;
       }
   
       temp = doc.body.appendChild( doc.createElement( nodeName ) );
       display = jQuery.css( temp, "display" );
   
       temp.parentNode.removeChild( temp );
   
       if ( display === "none" ) {
           display = "block";
       }
       defaultDisplayMap[ nodeName ] = display;
   
       return display;
   }
   
   function showHide( elements, show ) {
       var display, elem,
           values = [],
           index = 0,
           length = elements.length;
   
       // Determine new display value for elements that need to change
       for ( ; index < length; index++ ) {
           elem = elements[ index ];
           if ( !elem.style ) {
               continue;
           }
   
           display = elem.style.display;
           if ( show ) {
   
               // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
               // check is required in this first loop unless we have a nonempty display value (either
               // inline or about-to-be-restored)
               if ( display === "none" ) {
                   values[ index ] = dataPriv.get( elem, "display" ) || null;
                   if ( !values[ index ] ) {
                       elem.style.display = "";
                   }
               }
               if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
                   values[ index ] = getDefaultDisplay( elem );
               }
           } else {
               if ( display !== "none" ) {
                   values[ index ] = "none";
   
                   // Remember what we're overwriting
                   dataPriv.set( elem, "display", display );
               }
           }
       }
   
       // Set the display of the elements in a second loop to avoid constant reflow
       for ( index = 0; index < length; index++ ) {
           if ( values[ index ] != null ) {
               elements[ index ].style.display = values[ index ];
           }
       }
   
       return elements;
   }
   
   jQuery.fn.extend( {
       show: function() {
           return showHide( this, true );
       },
       hide: function() {
           return showHide( this );
       },
       toggle: function( state ) {
           if ( typeof state === "boolean" ) {
               return state ? this.show() : this.hide();
           }
   
           return this.each( function() {
               if ( isHiddenWithinTree( this ) ) {
                   jQuery( this ).show();
               } else {
                   jQuery( this ).hide();
               }
           } );
       }
   } );
   var rcheckableType = ( /^(?:checkbox|radio)$/i );
   
   var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
   
   var rscriptType = ( /^$|\/(?:java|ecma)script/i );
   
   
   
   // We have to close these tags to support XHTML (#13200)
   var wrapMap = {
   
       // Support: IE <=9 only
       option: [ 1, "<select multiple='multiple'>", "</select>" ],
   
       // XHTML parsers do not magically insert elements in the
       // same way that tag soup parsers do. So we cannot shorten
       // this by omitting <tbody> or other required elements.
       thead: [ 1, "<table>", "</table>" ],
       col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
       tr: [ 2, "<table><tbody>", "</tbody></table>" ],
       td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
   
       _default: [ 0, "", "" ]
   };
   
   // Support: IE <=9 only
   wrapMap.optgroup = wrapMap.option;
   
   wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
   wrapMap.th = wrapMap.td;
   
   
   function getAll( context, tag ) {
   
       // Support: IE <=9 - 11 only
       // Use typeof to avoid zero-argument method invocation on host objects (#15151)
       var ret;
   
       if ( typeof context.getElementsByTagName !== "undefined" ) {
           ret = context.getElementsByTagName( tag || "*" );
   
       } else if ( typeof context.querySelectorAll !== "undefined" ) {
           ret = context.querySelectorAll( tag || "*" );
   
       } else {
           ret = [];
       }
   
       if ( tag === undefined || tag && nodeName( context, tag ) ) {
           return jQuery.merge( [ context ], ret );
       }
   
       return ret;
   }
   
   
   // Mark scripts as having already been evaluated
   function setGlobalEval( elems, refElements ) {
       var i = 0,
           l = elems.length;
   
       for ( ; i < l; i++ ) {
           dataPriv.set(
               elems[ i ],
               "globalEval",
               !refElements || dataPriv.get( refElements[ i ], "globalEval" )
           );
       }
   }
   
   
   var rhtml = /<|&#?\w+;/;
   
   function buildFragment( elems, context, scripts, selection, ignored ) {
       var elem, tmp, tag, wrap, contains, j,
           fragment = context.createDocumentFragment(),
           nodes = [],
           i = 0,
           l = elems.length;
   
       for ( ; i < l; i++ ) {
           elem = elems[ i ];
   
           if ( elem || elem === 0 ) {
   
               // Add nodes directly
               if ( jQuery.type( elem ) === "object" ) {
   
                   // Support: Android <=4.0 only, PhantomJS 1 only
                   // push.apply(_, arraylike) throws on ancient WebKit
                   jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
   
               // Convert non-html into a text node
               } else if ( !rhtml.test( elem ) ) {
                   nodes.push( context.createTextNode( elem ) );
   
               // Convert html into DOM nodes
               } else {
                   tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
   
                   // Deserialize a standard representation
                   tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
                   wrap = wrapMap[ tag ] || wrapMap._default;
                   tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
   
                   // Descend through wrappers to the right content
                   j = wrap[ 0 ];
                   while ( j-- ) {
                       tmp = tmp.lastChild;
                   }
   
                   // Support: Android <=4.0 only, PhantomJS 1 only
                   // push.apply(_, arraylike) throws on ancient WebKit
                   jQuery.merge( nodes, tmp.childNodes );
   
                   // Remember the top-level container
                   tmp = fragment.firstChild;
   
                   // Ensure the created nodes are orphaned (#12392)
                   tmp.textContent = "";
               }
           }
       }
   
       // Remove wrapper from fragment
       fragment.textContent = "";
   
       i = 0;
       while ( ( elem = nodes[ i++ ] ) ) {
   
           // Skip elements already in the context collection (trac-4087)
           if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
               if ( ignored ) {
                   ignored.push( elem );
               }
               continue;
           }
   
           contains = jQuery.contains( elem.ownerDocument, elem );
   
           // Append to fragment
           tmp = getAll( fragment.appendChild( elem ), "script" );
   
           // Preserve script evaluation history
           if ( contains ) {
               setGlobalEval( tmp );
           }
   
           // Capture executables
           if ( scripts ) {
               j = 0;
               while ( ( elem = tmp[ j++ ] ) ) {
                   if ( rscriptType.test( elem.type || "" ) ) {
                       scripts.push( elem );
                   }
               }
           }
       }
   
       return fragment;
   }
   
   
   ( function() {
       var fragment = document.createDocumentFragment(),
           div = fragment.appendChild( document.createElement( "div" ) ),
           input = document.createElement( "input" );
   
       // Support: Android 4.0 - 4.3 only
       // Check state lost if the name is set (#11217)
       // Support: Windows Web Apps (WWA)
       // `name` and `type` must use .setAttribute for WWA (#14901)
       input.setAttribute( "type", "radio" );
       input.setAttribute( "checked", "checked" );
       input.setAttribute( "name", "t" );
   
       div.appendChild( input );
   
       // Support: Android <=4.1 only
       // Older WebKit doesn't clone checked state correctly in fragments
       support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
   
       // Support: IE <=11 only
       // Make sure textarea (and checkbox) defaultValue is properly cloned
       div.innerHTML = "<textarea>x</textarea>";
       support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
   } )();
   var documentElement = document.documentElement;
   
   
   
   var
       rkeyEvent = /^key/,
       rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
       rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
   
   function returnTrue() {
       return true;
   }
   
   function returnFalse() {
       return false;
   }
   
   // Support: IE <=9 only
   // See #13393 for more info
   function safeActiveElement() {
       try {
           return document.activeElement;
       } catch ( err ) { }
   }
   
   function on( elem, types, selector, data, fn, one ) {
       var origFn, type;
   
       // Types can be a map of types/handlers
       if ( typeof types === "object" ) {
   
           // ( types-Object, selector, data )
           if ( typeof selector !== "string" ) {
   
               // ( types-Object, data )
               data = data || selector;
               selector = undefined;
           }
           for ( type in types ) {
               on( elem, type, selector, data, types[ type ], one );
           }
           return elem;
       }
   
       if ( data == null && fn == null ) {
   
           // ( types, fn )
           fn = selector;
           data = selector = undefined;
       } else if ( fn == null ) {
           if ( typeof selector === "string" ) {
   
               // ( types, selector, fn )
               fn = data;
               data = undefined;
           } else {
   
               // ( types, data, fn )
               fn = data;
               data = selector;
               selector = undefined;
           }
       }
       if ( fn === false ) {
           fn = returnFalse;
       } else if ( !fn ) {
           return elem;
       }
   
       if ( one === 1 ) {
           origFn = fn;
           fn = function( event ) {
   
               // Can use an empty set, since event contains the info
               jQuery().off( event );
               return origFn.apply( this, arguments );
           };
   
           // Use same guid so caller can remove using origFn
           fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
       }
       return elem.each( function() {
           jQuery.event.add( this, types, fn, data, selector );
       } );
   }
   
   /*
    * Helper functions for managing events -- not part of the public interface.
    * Props to Dean Edwards' addEvent library for many of the ideas.
    */
   jQuery.event = {
   
       global: {},
   
       add: function( elem, types, handler, data, selector ) {
   
           var handleObjIn, eventHandle, tmp,
               events, t, handleObj,
               special, handlers, type, namespaces, origType,
               elemData = dataPriv.get( elem );
   
           // Don't attach events to noData or text/comment nodes (but allow plain objects)
           if ( !elemData ) {
               return;
           }
   
           // Caller can pass in an object of custom data in lieu of the handler
           if ( handler.handler ) {
               handleObjIn = handler;
               handler = handleObjIn.handler;
               selector = handleObjIn.selector;
           }
   
           // Ensure that invalid selectors throw exceptions at attach time
           // Evaluate against documentElement in case elem is a non-element node (e.g., document)
           if ( selector ) {
               jQuery.find.matchesSelector( documentElement, selector );
           }
   
           // Make sure that the handler has a unique ID, used to find/remove it later
           if ( !handler.guid ) {
               handler.guid = jQuery.guid++;
           }
   
           // Init the element's event structure and main handler, if this is the first
           if ( !( events = elemData.events ) ) {
               events = elemData.events = {};
           }
           if ( !( eventHandle = elemData.handle ) ) {
               eventHandle = elemData.handle = function( e ) {
   
                   // Discard the second event of a jQuery.event.trigger() and
                   // when an event is called after a page has unloaded
                   return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
                       jQuery.event.dispatch.apply( elem, arguments ) : undefined;
               };
           }
   
           // Handle multiple events separated by a space
           types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
           t = types.length;
           while ( t-- ) {
               tmp = rtypenamespace.exec( types[ t ] ) || [];
               type = origType = tmp[ 1 ];
               namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
   
               // There *must* be a type, no attaching namespace-only handlers
               if ( !type ) {
                   continue;
               }
   
               // If event changes its type, use the special event handlers for the changed type
               special = jQuery.event.special[ type ] || {};
   
               // If selector defined, determine special event api type, otherwise given type
               type = ( selector ? special.delegateType : special.bindType ) || type;
   
               // Update special based on newly reset type
               special = jQuery.event.special[ type ] || {};
   
               // handleObj is passed to all event handlers
               handleObj = jQuery.extend( {
                   type: type,
                   origType: origType,
                   data: data,
                   handler: handler,
                   guid: handler.guid,
                   selector: selector,
                   needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
                   namespace: namespaces.join( "." )
               }, handleObjIn );
   
               // Init the event handler queue if we're the first
               if ( !( handlers = events[ type ] ) ) {
                   handlers = events[ type ] = [];
                   handlers.delegateCount = 0;
   
                   // Only use addEventListener if the special events handler returns false
                   if ( !special.setup ||
                       special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
   
                       if ( elem.addEventListener ) {
                           elem.addEventListener( type, eventHandle );
                       }
                   }
               }
   
               if ( special.add ) {
                   special.add.call( elem, handleObj );
   
                   if ( !handleObj.handler.guid ) {
                       handleObj.handler.guid = handler.guid;
                   }
               }
   
               // Add to the element's handler list, delegates in front
               if ( selector ) {
                   handlers.splice( handlers.delegateCount++, 0, handleObj );
               } else {
                   handlers.push( handleObj );
               }
   
               // Keep track of which events have ever been used, for event optimization
               jQuery.event.global[ type ] = true;
           }
   
       },
   
       // Detach an event or set of events from an element
       remove: function( elem, types, handler, selector, mappedTypes ) {
   
           var j, origCount, tmp,
               events, t, handleObj,
               special, handlers, type, namespaces, origType,
               elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
   
           if ( !elemData || !( events = elemData.events ) ) {
               return;
           }
   
           // Once for each type.namespace in types; type may be omitted
           types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
           t = types.length;
           while ( t-- ) {
               tmp = rtypenamespace.exec( types[ t ] ) || [];
               type = origType = tmp[ 1 ];
               namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
   
               // Unbind all events (on this namespace, if provided) for the element
               if ( !type ) {
                   for ( type in events ) {
                       jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
                   }
                   continue;
               }
   
               special = jQuery.event.special[ type ] || {};
               type = ( selector ? special.delegateType : special.bindType ) || type;
               handlers = events[ type ] || [];
               tmp = tmp[ 2 ] &&
                   new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
   
               // Remove matching events
               origCount = j = handlers.length;
               while ( j-- ) {
                   handleObj = handlers[ j ];
   
                   if ( ( mappedTypes || origType === handleObj.origType ) &&
                       ( !handler || handler.guid === handleObj.guid ) &&
                       ( !tmp || tmp.test( handleObj.namespace ) ) &&
                       ( !selector || selector === handleObj.selector ||
                           selector === "**" && handleObj.selector ) ) {
                       handlers.splice( j, 1 );
   
                       if ( handleObj.selector ) {
                           handlers.delegateCount--;
                       }
                       if ( special.remove ) {
                           special.remove.call( elem, handleObj );
                       }
                   }
               }
   
               // Remove generic event handler if we removed something and no more handlers exist
               // (avoids potential for endless recursion during removal of special event handlers)
               if ( origCount && !handlers.length ) {
                   if ( !special.teardown ||
                       special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
   
                       jQuery.removeEvent( elem, type, elemData.handle );
                   }
   
                   delete events[ type ];
               }
           }
   
           // Remove data and the expando if it's no longer used
           if ( jQuery.isEmptyObject( events ) ) {
               dataPriv.remove( elem, "handle events" );
           }
       },
   
       dispatch: function( nativeEvent ) {
   
           // Make a writable jQuery.Event from the native event object
           var event = jQuery.event.fix( nativeEvent );
   
           var i, j, ret, matched, handleObj, handlerQueue,
               args = new Array( arguments.length ),
               handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
               special = jQuery.event.special[ event.type ] || {};
   
           // Use the fix-ed jQuery.Event rather than the (read-only) native event
           args[ 0 ] = event;
   
           for ( i = 1; i < arguments.length; i++ ) {
               args[ i ] = arguments[ i ];
           }
   
           event.delegateTarget = this;
   
           // Call the preDispatch hook for the mapped type, and let it bail if desired
           if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
               return;
           }
   
           // Determine handlers
           handlerQueue = jQuery.event.handlers.call( this, event, handlers );
   
           // Run delegates first; they may want to stop propagation beneath us
           i = 0;
           while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
               event.currentTarget = matched.elem;
   
               j = 0;
               while ( ( handleObj = matched.handlers[ j++ ] ) &&
                   !event.isImmediatePropagationStopped() ) {
   
                   // Triggered event must either 1) have no namespace, or 2) have namespace(s)
                   // a subset or equal to those in the bound event (both can have no namespace).
                   if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
   
                       event.handleObj = handleObj;
                       event.data = handleObj.data;
   
                       ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
                           handleObj.handler ).apply( matched.elem, args );
   
                       if ( ret !== undefined ) {
                           if ( ( event.result = ret ) === false ) {
                               event.preventDefault();
                               event.stopPropagation();
                           }
                       }
                   }
               }
           }
   
           // Call the postDispatch hook for the mapped type
           if ( special.postDispatch ) {
               special.postDispatch.call( this, event );
           }
   
           return event.result;
       },
   
       handlers: function( event, handlers ) {
           var i, handleObj, sel, matchedHandlers, matchedSelectors,
               handlerQueue = [],
               delegateCount = handlers.delegateCount,
               cur = event.target;
   
           // Find delegate handlers
           if ( delegateCount &&
   
               // Support: IE <=9
               // Black-hole SVG <use> instance trees (trac-13180)
               cur.nodeType &&
   
               // Support: Firefox <=42
               // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
               // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
               // Support: IE 11 only
               // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
               !( event.type === "click" && event.button >= 1 ) ) {
   
               for ( ; cur !== this; cur = cur.parentNode || this ) {
   
                   // Don't check non-elements (#13208)
                   // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
                   if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
                       matchedHandlers = [];
                       matchedSelectors = {};
                       for ( i = 0; i < delegateCount; i++ ) {
                           handleObj = handlers[ i ];
   
                           // Don't conflict with Object.prototype properties (#13203)
                           sel = handleObj.selector + " ";
   
                           if ( matchedSelectors[ sel ] === undefined ) {
                               matchedSelectors[ sel ] = handleObj.needsContext ?
                                   jQuery( sel, this ).index( cur ) > -1 :
                                   jQuery.find( sel, this, null, [ cur ] ).length;
                           }
                           if ( matchedSelectors[ sel ] ) {
                               matchedHandlers.push( handleObj );
                           }
                       }
                       if ( matchedHandlers.length ) {
                           handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
                       }
                   }
               }
           }
   
           // Add the remaining (directly-bound) handlers
           cur = this;
           if ( delegateCount < handlers.length ) {
               handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
           }
   
           return handlerQueue;
       },
   
       addProp: function( name, hook ) {
           Object.defineProperty( jQuery.Event.prototype, name, {
               enumerable: true,
               configurable: true,
   
               get: jQuery.isFunction( hook ) ?
                   function() {
                       if ( this.originalEvent ) {
                               return hook( this.originalEvent );
                       }
                   } :
                   function() {
                       if ( this.originalEvent ) {
                               return this.originalEvent[ name ];
                       }
                   },
   
               set: function( value ) {
                   Object.defineProperty( this, name, {
                       enumerable: true,
                       configurable: true,
                       writable: true,
                       value: value
                   } );
               }
           } );
       },
   
       fix: function( originalEvent ) {
           return originalEvent[ jQuery.expando ] ?
               originalEvent :
               new jQuery.Event( originalEvent );
       },
   
       special: {
           load: {
   
               // Prevent triggered image.load events from bubbling to window.load
               noBubble: true
           },
           focus: {
   
               // Fire native event if possible so blur/focus sequence is correct
               trigger: function() {
                   if ( this !== safeActiveElement() && this.focus ) {
                       this.focus();
                       return false;
                   }
               },
               delegateType: "focusin"
           },
           blur: {
               trigger: function() {
                   if ( this === safeActiveElement() && this.blur ) {
                       this.blur();
                       return false;
                   }
               },
               delegateType: "focusout"
           },
           click: {
   
               // For checkbox, fire native event so checked state will be right
               trigger: function() {
                   if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
                       this.click();
                       return false;
                   }
               },
   
               // For cross-browser consistency, don't fire native .click() on links
               _default: function( event ) {
                   return nodeName( event.target, "a" );
               }
           },
   
           beforeunload: {
               postDispatch: function( event ) {
   
                   // Support: Firefox 20+
                   // Firefox doesn't alert if the returnValue field is not set.
                   if ( event.result !== undefined && event.originalEvent ) {
                       event.originalEvent.returnValue = event.result;
                   }
               }
           }
       }
   };
   
   jQuery.removeEvent = function( elem, type, handle ) {
   
       // This "if" is needed for plain objects
       if ( elem.removeEventListener ) {
           elem.removeEventListener( type, handle );
       }
   };
   
   jQuery.Event = function( src, props ) {
   
       // Allow instantiation without the 'new' keyword
       if ( !( this instanceof jQuery.Event ) ) {
           return new jQuery.Event( src, props );
       }
   
       // Event object
       if ( src && src.type ) {
           this.originalEvent = src;
           this.type = src.type;
   
           // Events bubbling up the document may have been marked as prevented
           // by a handler lower down the tree; reflect the correct value.
           this.isDefaultPrevented = src.defaultPrevented ||
                   src.defaultPrevented === undefined &&
   
                   // Support: Android <=2.3 only
                   src.returnValue === false ?
               returnTrue :
               returnFalse;
   
           // Create target properties
           // Support: Safari <=6 - 7 only
           // Target should not be a text node (#504, #13143)
           this.target = ( src.target && src.target.nodeType === 3 ) ?
               src.target.parentNode :
               src.target;
   
           this.currentTarget = src.currentTarget;
           this.relatedTarget = src.relatedTarget;
   
       // Event type
       } else {
           this.type = src;
       }
   
       // Put explicitly provided properties onto the event object
       if ( props ) {
           jQuery.extend( this, props );
       }
   
       // Create a timestamp if incoming event doesn't have one
       this.timeStamp = src && src.timeStamp || jQuery.now();
   
       // Mark it as fixed
       this[ jQuery.expando ] = true;
   };
   
   // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
   // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
   jQuery.Event.prototype = {
       constructor: jQuery.Event,
       isDefaultPrevented: returnFalse,
       isPropagationStopped: returnFalse,
       isImmediatePropagationStopped: returnFalse,
       isSimulated: false,
   
       preventDefault: function() {
           var e = this.originalEvent;
   
           this.isDefaultPrevented = returnTrue;
   
           if ( e && !this.isSimulated ) {
               e.preventDefault();
           }
       },
       stopPropagation: function() {
           var e = this.originalEvent;
   
           this.isPropagationStopped = returnTrue;
   
           if ( e && !this.isSimulated ) {
               e.stopPropagation();
           }
       },
       stopImmediatePropagation: function() {
           var e = this.originalEvent;
   
           this.isImmediatePropagationStopped = returnTrue;
   
           if ( e && !this.isSimulated ) {
               e.stopImmediatePropagation();
           }
   
           this.stopPropagation();
       }
   };
   
   // Includes all common event props including KeyEvent and MouseEvent specific props
   jQuery.each( {
       altKey: true,
       bubbles: true,
       cancelable: true,
       changedTouches: true,
       ctrlKey: true,
       detail: true,
       eventPhase: true,
       metaKey: true,
       pageX: true,
       pageY: true,
       shiftKey: true,
       view: true,
       "char": true,
       charCode: true,
       key: true,
       keyCode: true,
       button: true,
       buttons: true,
       clientX: true,
       clientY: true,
       offsetX: true,
       offsetY: true,
       pointerId: true,
       pointerType: true,
       screenX: true,
       screenY: true,
       targetTouches: true,
       toElement: true,
       touches: true,
   
       which: function( event ) {
           var button = event.button;
   
           // Add which for key events
           if ( event.which == null && rkeyEvent.test( event.type ) ) {
               return event.charCode != null ? event.charCode : event.keyCode;
           }
   
           // Add which for click: 1 === left; 2 === middle; 3 === right
           if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
               if ( button & 1 ) {
                   return 1;
               }
   
               if ( button & 2 ) {
                   return 3;
               }
   
               if ( button & 4 ) {
                   return 2;
               }
   
               return 0;
           }
   
           return event.which;
       }
   }, jQuery.event.addProp );
   
   // Create mouseenter/leave events using mouseover/out and event-time checks
   // so that event delegation works in jQuery.
   // Do the same for pointerenter/pointerleave and pointerover/pointerout
   //
   // Support: Safari 7 only
   // Safari sends mouseenter too often; see:
   // https://bugs.chromium.org/p/chromium/issues/detail?id=470258
   // for the description of the bug (it existed in older Chrome versions as well).
   jQuery.each( {
       mouseenter: "mouseover",
       mouseleave: "mouseout",
       pointerenter: "pointerover",
       pointerleave: "pointerout"
   }, function( orig, fix ) {
       jQuery.event.special[ orig ] = {
           delegateType: fix,
           bindType: fix,
   
           handle: function( event ) {
               var ret,
                   target = this,
                   related = event.relatedTarget,
                   handleObj = event.handleObj;
   
               // For mouseenter/leave call the handler if related is outside the target.
               // NB: No relatedTarget if the mouse left/entered the browser window
               if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
                   event.type = handleObj.origType;
                   ret = handleObj.handler.apply( this, arguments );
                   event.type = fix;
               }
               return ret;
           }
       };
   } );
   
   jQuery.fn.extend( {
   
       on: function( types, selector, data, fn ) {
           return on( this, types, selector, data, fn );
       },
       one: function( types, selector, data, fn ) {
           return on( this, types, selector, data, fn, 1 );
       },
       off: function( types, selector, fn ) {
           var handleObj, type;
           if ( types && types.preventDefault && types.handleObj ) {
   
               // ( event )  dispatched jQuery.Event
               handleObj = types.handleObj;
               jQuery( types.delegateTarget ).off(
                   handleObj.namespace ?
                       handleObj.origType + "." + handleObj.namespace :
                       handleObj.origType,
                   handleObj.selector,
                   handleObj.handler
               );
               return this;
           }
           if ( typeof types === "object" ) {
   
               // ( types-object [, selector] )
               for ( type in types ) {
                   this.off( type, selector, types[ type ] );
               }
               return this;
           }
           if ( selector === false || typeof selector === "function" ) {
   
               // ( types [, fn] )
               fn = selector;
               selector = undefined;
           }
           if ( fn === false ) {
               fn = returnFalse;
           }
           return this.each( function() {
               jQuery.event.remove( this, types, fn, selector );
           } );
       }
   } );
   
   
   var
   
       /* eslint-disable max-len */
   
       // See https://github.com/eslint/eslint/issues/3229
       rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
   
       /* eslint-enable */
   
       // Support: IE <=10 - 11, Edge 12 - 13
       // In IE/Edge using regex groups here causes severe slowdowns.
       // See https://connect.microsoft.com/IE/feedback/details/1736512/
       rnoInnerhtml = /<script|<style|<link/i,
   
       // checked="checked" or checked
       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
       rscriptTypeMasked = /^true\/(.*)/,
       rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
   
   // Prefer a tbody over its parent table for containing new rows
   function manipulationTarget( elem, content ) {
       if ( nodeName( elem, "table" ) &&
           nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
   
           return jQuery( ">tbody", elem )[ 0 ] || elem;
       }
   
       return elem;
   }
   
   // Replace/restore the type attribute of script elements for safe DOM manipulation
   function disableScript( elem ) {
       elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
       return elem;
   }
   function restoreScript( elem ) {
       var match = rscriptTypeMasked.exec( elem.type );
   
       if ( match ) {
           elem.type = match[ 1 ];
       } else {
           elem.removeAttribute( "type" );
       }
   
       return elem;
   }
   
   function cloneCopyEvent( src, dest ) {
       var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
   
       if ( dest.nodeType !== 1 ) {
           return;
       }
   
       // 1. Copy private data: events, handlers, etc.
       if ( dataPriv.hasData( src ) ) {
           pdataOld = dataPriv.access( src );
           pdataCur = dataPriv.set( dest, pdataOld );
           events = pdataOld.events;
   
           if ( events ) {
               delete pdataCur.handle;
               pdataCur.events = {};
   
               for ( type in events ) {
                   for ( i = 0, l = events[ type ].length; i < l; i++ ) {
                       jQuery.event.add( dest, type, events[ type ][ i ] );
                   }
               }
           }
       }
   
       // 2. Copy user data
       if ( dataUser.hasData( src ) ) {
           udataOld = dataUser.access( src );
           udataCur = jQuery.extend( {}, udataOld );
   
           dataUser.set( dest, udataCur );
       }
   }
   
   // Fix IE bugs, see support tests
   function fixInput( src, dest ) {
       var nodeName = dest.nodeName.toLowerCase();
   
       // Fails to persist the checked state of a cloned checkbox or radio button.
       if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
           dest.checked = src.checked;
   
       // Fails to return the selected option to the default selected state when cloning options
       } else if ( nodeName === "input" || nodeName === "textarea" ) {
           dest.defaultValue = src.defaultValue;
       }
   }
   
   function domManip( collection, args, callback, ignored ) {
   
       // Flatten any nested arrays
       args = concat.apply( [], args );
   
       var fragment, first, scripts, hasScripts, node, doc,
           i = 0,
           l = collection.length,
           iNoClone = l - 1,
           value = args[ 0 ],
           isFunction = jQuery.isFunction( value );
   
       // We can't cloneNode fragments that contain checked, in WebKit
       if ( isFunction ||
               ( l > 1 && typeof value === "string" &&
                   !support.checkClone && rchecked.test( value ) ) ) {
           return collection.each( function( index ) {
               var self = collection.eq( index );
               if ( isFunction ) {
                   args[ 0 ] = value.call( this, index, self.html() );
               }
               domManip( self, args, callback, ignored );
           } );
       }
   
       if ( l ) {
           fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
           first = fragment.firstChild;
   
           if ( fragment.childNodes.length === 1 ) {
               fragment = first;
           }
   
           // Require either new content or an interest in ignored elements to invoke the callback
           if ( first || ignored ) {
               scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
               hasScripts = scripts.length;
   
               // Use the original fragment for the last item
               // instead of the first because it can end up
               // being emptied incorrectly in certain situations (#8070).
               for ( ; i < l; i++ ) {
                   node = fragment;
   
                   if ( i !== iNoClone ) {
                       node = jQuery.clone( node, true, true );
   
                       // Keep references to cloned scripts for later restoration
                       if ( hasScripts ) {
   
                           // Support: Android <=4.0 only, PhantomJS 1 only
                           // push.apply(_, arraylike) throws on ancient WebKit
                           jQuery.merge( scripts, getAll( node, "script" ) );
                       }
                   }
   
                   callback.call( collection[ i ], node, i );
               }
   
               if ( hasScripts ) {
                   doc = scripts[ scripts.length - 1 ].ownerDocument;
   
                   // Reenable scripts
                   jQuery.map( scripts, restoreScript );
   
                   // Evaluate executable scripts on first document insertion
                   for ( i = 0; i < hasScripts; i++ ) {
                       node = scripts[ i ];
                       if ( rscriptType.test( node.type || "" ) &&
                           !dataPriv.access( node, "globalEval" ) &&
                           jQuery.contains( doc, node ) ) {
   
                           if ( node.src ) {
   
                               // Optional AJAX dependency, but won't run scripts if not present
                               if ( jQuery._evalUrl ) {
                                   jQuery._evalUrl( node.src );
                               }
                           } else {
                               DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
                           }
                       }
                   }
               }
           }
       }
   
       return collection;
   }
   
   function remove( elem, selector, keepData ) {
       var node,
           nodes = selector ? jQuery.filter( selector, elem ) : elem,
           i = 0;
   
       for ( ; ( node = nodes[ i ] ) != null; i++ ) {
           if ( !keepData && node.nodeType === 1 ) {
               jQuery.cleanData( getAll( node ) );
           }
   
           if ( node.parentNode ) {
               if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
                   setGlobalEval( getAll( node, "script" ) );
               }
               node.parentNode.removeChild( node );
           }
       }
   
       return elem;
   }
   
   jQuery.extend( {
       htmlPrefilter: function( html ) {
           return html.replace( rxhtmlTag, "<$1></$2>" );
       },
   
       clone: function( elem, dataAndEvents, deepDataAndEvents ) {
           var i, l, srcElements, destElements,
               clone = elem.cloneNode( true ),
               inPage = jQuery.contains( elem.ownerDocument, elem );
   
           // Fix IE cloning issues
           if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
                   !jQuery.isXMLDoc( elem ) ) {
   
               // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
               destElements = getAll( clone );
               srcElements = getAll( elem );
   
               for ( i = 0, l = srcElements.length; i < l; i++ ) {
                   fixInput( srcElements[ i ], destElements[ i ] );
               }
           }
   
           // Copy the events from the original to the clone
           if ( dataAndEvents ) {
               if ( deepDataAndEvents ) {
                   srcElements = srcElements || getAll( elem );
                   destElements = destElements || getAll( clone );
   
                   for ( i = 0, l = srcElements.length; i < l; i++ ) {
                       cloneCopyEvent( srcElements[ i ], destElements[ i ] );
                   }
               } else {
                   cloneCopyEvent( elem, clone );
               }
           }
   
           // Preserve script evaluation history
           destElements = getAll( clone, "script" );
           if ( destElements.length > 0 ) {
               setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
           }
   
           // Return the cloned set
           return clone;
       },
   
       cleanData: function( elems ) {
           var data, elem, type,
               special = jQuery.event.special,
               i = 0;
   
           for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
               if ( acceptData( elem ) ) {
                   if ( ( data = elem[ dataPriv.expando ] ) ) {
                       if ( data.events ) {
                           for ( type in data.events ) {
                               if ( special[ type ] ) {
                                   jQuery.event.remove( elem, type );
   
                               // This is a shortcut to avoid jQuery.event.remove's overhead
                               } else {
                                   jQuery.removeEvent( elem, type, data.handle );
                               }
                           }
                       }
   
                       // Support: Chrome <=35 - 45+
                       // Assign undefined instead of using delete, see Data#remove
                       elem[ dataPriv.expando ] = undefined;
                   }
                   if ( elem[ dataUser.expando ] ) {
   
                       // Support: Chrome <=35 - 45+
                       // Assign undefined instead of using delete, see Data#remove
                       elem[ dataUser.expando ] = undefined;
                   }
               }
           }
       }
   } );
   
   jQuery.fn.extend( {
       detach: function( selector ) {
           return remove( this, selector, true );
       },
   
       remove: function( selector ) {
           return remove( this, selector );
       },
   
       text: function( value ) {
           return access( this, function( value ) {
               return value === undefined ?
                   jQuery.text( this ) :
                   this.empty().each( function() {
                       if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                           this.textContent = value;
                       }
                   } );
           }, null, value, arguments.length );
       },
   
       append: function() {
           return domManip( this, arguments, function( elem ) {
               if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                   var target = manipulationTarget( this, elem );
                   target.appendChild( elem );
               }
           } );
       },
   
       prepend: function() {
           return domManip( this, arguments, function( elem ) {
               if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
                   var target = manipulationTarget( this, elem );
                   target.insertBefore( elem, target.firstChild );
               }
           } );
       },
   
       before: function() {
           return domManip( this, arguments, function( elem ) {
               if ( this.parentNode ) {
                   this.parentNode.insertBefore( elem, this );
               }
           } );
       },
   
       after: function() {
           return domManip( this, arguments, function( elem ) {
               if ( this.parentNode ) {
                   this.parentNode.insertBefore( elem, this.nextSibling );
               }
           } );
       },
   
       empty: function() {
           var elem,
               i = 0;
   
           for ( ; ( elem = this[ i ] ) != null; i++ ) {
               if ( elem.nodeType === 1 ) {
   
                   // Prevent memory leaks
                   jQuery.cleanData( getAll( elem, false ) );
   
                   // Remove any remaining nodes
                   elem.textContent = "";
               }
           }
   
           return this;
       },
   
       clone: function( dataAndEvents, deepDataAndEvents ) {
           dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
           deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
   
           return this.map( function() {
               return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
           } );
       },
   
       html: function( value ) {
           return access( this, function( value ) {
               var elem = this[ 0 ] || {},
                   i = 0,
                   l = this.length;
   
               if ( value === undefined && elem.nodeType === 1 ) {
                   return elem.innerHTML;
               }
   
               // See if we can take a shortcut and just use innerHTML
               if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
                   !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
   
                   value = jQuery.htmlPrefilter( value );
   
                   try {
                       for ( ; i < l; i++ ) {
                           elem = this[ i ] || {};
   
                           // Remove element nodes and prevent memory leaks
                           if ( elem.nodeType === 1 ) {
                               jQuery.cleanData( getAll( elem, false ) );
                               elem.innerHTML = value;
                           }
                       }
   
                       elem = 0;
   
                   // If using innerHTML throws an exception, use the fallback method
                   } catch ( e ) {}
               }
   
               if ( elem ) {
                   this.empty().append( value );
               }
           }, null, value, arguments.length );
       },
   
       replaceWith: function() {
           var ignored = [];
   
           // Make the changes, replacing each non-ignored context element with the new content
           return domManip( this, arguments, function( elem ) {
               var parent = this.parentNode;
   
               if ( jQuery.inArray( this, ignored ) < 0 ) {
                   jQuery.cleanData( getAll( this ) );
                   if ( parent ) {
                       parent.replaceChild( elem, this );
                   }
               }
   
           // Force callback invocation
           }, ignored );
       }
   } );
   
   jQuery.each( {
       appendTo: "append",
       prependTo: "prepend",
       insertBefore: "before",
       insertAfter: "after",
       replaceAll: "replaceWith"
   }, function( name, original ) {
       jQuery.fn[ name ] = function( selector ) {
           var elems,
               ret = [],
               insert = jQuery( selector ),
               last = insert.length - 1,
               i = 0;
   
           for ( ; i <= last; i++ ) {
               elems = i === last ? this : this.clone( true );
               jQuery( insert[ i ] )[ original ]( elems );
   
               // Support: Android <=4.0 only, PhantomJS 1 only
               // .get() because push.apply(_, arraylike) throws on ancient WebKit
               push.apply( ret, elems.get() );
           }
   
           return this.pushStack( ret );
       };
   } );
   var rmargin = ( /^margin/ );
   
   var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
   
   var getStyles = function( elem ) {
   
           // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
           // IE throws on elements created in popups
           // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
           var view = elem.ownerDocument.defaultView;
   
           if ( !view || !view.opener ) {
               view = window;
           }
   
           return view.getComputedStyle( elem );
       };
   
   
   
   ( function() {
   
       // Executing both pixelPosition & boxSizingReliable tests require only one layout
       // so they're executed at the same time to save the second computation.
       function computeStyleTests() {
   
           // This is a singleton, we need to execute it only once
           if ( !div ) {
               return;
           }
   
           div.style.cssText =
               "box-sizing:border-box;" +
               "position:relative;display:block;" +
               "margin:auto;border:1px;padding:1px;" +
               "top:1%;width:50%";
           div.innerHTML = "";
           documentElement.appendChild( container );
   
           var divStyle = window.getComputedStyle( div );
           pixelPositionVal = divStyle.top !== "1%";
   
           // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
           reliableMarginLeftVal = divStyle.marginLeft === "2px";
           boxSizingReliableVal = divStyle.width === "4px";
   
           // Support: Android 4.0 - 4.3 only
           // Some styles come back with percentage values, even though they shouldn't
           div.style.marginRight = "50%";
           pixelMarginRightVal = divStyle.marginRight === "4px";
   
           documentElement.removeChild( container );
   
           // Nullify the div so it wouldn't be stored in the memory and
           // it will also be a sign that checks already performed
           div = null;
       }
   
       var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
           container = document.createElement( "div" ),
           div = document.createElement( "div" );
   
       // Finish early in limited (non-browser) environments
       if ( !div.style ) {
           return;
       }
   
       // Support: IE <=9 - 11 only
       // Style of cloned element affects source element cloned (#8908)
       div.style.backgroundClip = "content-box";
       div.cloneNode( true ).style.backgroundClip = "";
       support.clearCloneStyle = div.style.backgroundClip === "content-box";
   
       container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
           "padding:0;margin-top:1px;position:absolute";
       container.appendChild( div );
   
       jQuery.extend( support, {
           pixelPosition: function() {
               computeStyleTests();
               return pixelPositionVal;
           },
           boxSizingReliable: function() {
               computeStyleTests();
               return boxSizingReliableVal;
           },
           pixelMarginRight: function() {
               computeStyleTests();
               return pixelMarginRightVal;
           },
           reliableMarginLeft: function() {
               computeStyleTests();
               return reliableMarginLeftVal;
           }
       } );
   } )();
   
   
   function curCSS( elem, name, computed ) {
       var width, minWidth, maxWidth, ret,
   
           // Support: Firefox 51+
           // Retrieving style before computed somehow
           // fixes an issue with getting wrong values
           // on detached elements
           style = elem.style;
   
       computed = computed || getStyles( elem );
   
       // getPropertyValue is needed for:
       //   .css('filter') (IE 9 only, #12537)
       //   .css('--customProperty) (#3144)
       if ( computed ) {
           ret = computed.getPropertyValue( name ) || computed[ name ];
   
           if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
               ret = jQuery.style( elem, name );
           }
   
           // A tribute to the "awesome hack by Dean Edwards"
           // Android Browser returns percentage for some values,
           // but width seems to be reliably pixels.
           // This is against the CSSOM draft spec:
           // https://drafts.csswg.org/cssom/#resolved-values
           if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
   
               // Remember the original values
               width = style.width;
               minWidth = style.minWidth;
               maxWidth = style.maxWidth;
   
               // Put in the new values to get a computed value out
               style.minWidth = style.maxWidth = style.width = ret;
               ret = computed.width;
   
               // Revert the changed values
               style.width = width;
               style.minWidth = minWidth;
               style.maxWidth = maxWidth;
           }
       }
   
       return ret !== undefined ?
   
           // Support: IE <=9 - 11 only
           // IE returns zIndex value as an integer.
           ret + "" :
           ret;
   }
   
   
   function addGetHookIf( conditionFn, hookFn ) {
   
       // Define the hook, we'll check on the first run if it's really needed.
       return {
           get: function() {
               if ( conditionFn() ) {
   
                   // Hook not needed (or it's not possible to use it due
                   // to missing dependency), remove it.
                   delete this.get;
                   return;
               }
   
               // Hook needed; redefine it so that the support test is not executed again.
               return ( this.get = hookFn ).apply( this, arguments );
           }
       };
   }
   
   
   var
   
       // Swappable if display is none or starts with table
       // except "table", "table-cell", or "table-caption"
       // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
       rdisplayswap = /^(none|table(?!-c[ea]).+)/,
       rcustomProp = /^--/,
       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
       cssNormalTransform = {
           letterSpacing: "0",
           fontWeight: "400"
       },
   
       cssPrefixes = [ "Webkit", "Moz", "ms" ],
       emptyStyle = document.createElement( "div" ).style;
   
   // Return a css property mapped to a potentially vendor prefixed property
   function vendorPropName( name ) {
   
       // Shortcut for names that are not vendor prefixed
       if ( name in emptyStyle ) {
           return name;
       }
   
       // Check for vendor prefixed names
       var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
           i = cssPrefixes.length;
   
       while ( i-- ) {
           name = cssPrefixes[ i ] + capName;
           if ( name in emptyStyle ) {
               return name;
           }
       }
   }
   
   // Return a property mapped along what jQuery.cssProps suggests or to
   // a vendor prefixed property.
   function finalPropName( name ) {
       var ret = jQuery.cssProps[ name ];
       if ( !ret ) {
           ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
       }
       return ret;
   }
   
   function setPositiveNumber( elem, value, subtract ) {
   
       // Any relative (+/-) values have already been
       // normalized at this point
       var matches = rcssNum.exec( value );
       return matches ?
   
           // Guard against undefined "subtract", e.g., when used as in cssHooks
           Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
           value;
   }
   
   function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
       var i,
           val = 0;
   
       // If we already have the right measurement, avoid augmentation
       if ( extra === ( isBorderBox ? "border" : "content" ) ) {
           i = 4;
   
       // Otherwise initialize for horizontal or vertical properties
       } else {
           i = name === "width" ? 1 : 0;
       }
   
       for ( ; i < 4; i += 2 ) {
   
           // Both box models exclude margin, so add it if we want it
           if ( extra === "margin" ) {
               val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
           }
   
           if ( isBorderBox ) {
   
               // border-box includes padding, so remove it if we want content
               if ( extra === "content" ) {
                   val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
               }
   
               // At this point, extra isn't border nor margin, so remove border
               if ( extra !== "margin" ) {
                   val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
               }
           } else {
   
               // At this point, extra isn't content, so add padding
               val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
   
               // At this point, extra isn't content nor padding, so add border
               if ( extra !== "padding" ) {
                   val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
               }
           }
       }
   
       return val;
   }
   
   function getWidthOrHeight( elem, name, extra ) {
   
       // Start with computed style
       var valueIsBorderBox,
           styles = getStyles( elem ),
           val = curCSS( elem, name, styles ),
           isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
   
       // Computed unit is not pixels. Stop here and return.
       if ( rnumnonpx.test( val ) ) {
           return val;
       }
   
       // Check for style in case a browser which returns unreliable values
       // for getComputedStyle silently falls back to the reliable elem.style
       valueIsBorderBox = isBorderBox &&
           ( support.boxSizingReliable() || val === elem.style[ name ] );
   
       // Fall back to offsetWidth/Height when value is "auto"
       // This happens for inline elements with no explicit setting (gh-3571)
       if ( val === "auto" ) {
           val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
       }
   
       // Normalize "", auto, and prepare for extra
       val = parseFloat( val ) || 0;
   
       // Use the active box-sizing model to add/subtract irrelevant styles
       return ( val +
           augmentWidthOrHeight(
               elem,
               name,
               extra || ( isBorderBox ? "border" : "content" ),
               valueIsBorderBox,
               styles
           )
       ) + "px";
   }
   
   jQuery.extend( {
   
       // Add in style property hooks for overriding the default
       // behavior of getting and setting a style property
       cssHooks: {
           opacity: {
               get: function( elem, computed ) {
                   if ( computed ) {
   
                       // We should always get a number back from opacity
                       var ret = curCSS( elem, "opacity" );
                       return ret === "" ? "1" : ret;
                   }
               }
           }
       },
   
       // Don't automatically add "px" to these possibly-unitless properties
       cssNumber: {
           "animationIterationCount": true,
           "columnCount": true,
           "fillOpacity": true,
           "flexGrow": true,
           "flexShrink": true,
           "fontWeight": true,
           "lineHeight": true,
           "opacity": true,
           "order": true,
           "orphans": true,
           "widows": true,
           "zIndex": true,
           "zoom": true
       },
   
       // Add in properties whose names you wish to fix before
       // setting or getting the value
       cssProps: {
           "float": "cssFloat"
       },
   
       // Get and set the style property on a DOM Node
       style: function( elem, name, value, extra ) {
   
           // Don't set styles on text and comment nodes
           if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
               return;
           }
   
           // Make sure that we're working with the right name
           var ret, type, hooks,
               origName = jQuery.camelCase( name ),
               isCustomProp = rcustomProp.test( name ),
               style = elem.style;
   
           // Make sure that we're working with the right name. We don't
           // want to query the value if it is a CSS custom property
           // since they are user-defined.
           if ( !isCustomProp ) {
               name = finalPropName( origName );
           }
   
           // Gets hook for the prefixed version, then unprefixed version
           hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
   
           // Check if we're setting a value
           if ( value !== undefined ) {
               type = typeof value;
   
               // Convert "+=" or "-=" to relative numbers (#7345)
               if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
                   value = adjustCSS( elem, name, ret );
   
                   // Fixes bug #9237
                   type = "number";
               }
   
               // Make sure that null and NaN values aren't set (#7116)
               if ( value == null || value !== value ) {
                   return;
               }
   
               // If a number was passed in, add the unit (except for certain CSS properties)
               if ( type === "number" ) {
                   value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
               }
   
               // background-* props affect original clone's values
               if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
                   style[ name ] = "inherit";
               }
   
               // If a hook was provided, use that value, otherwise just set the specified value
               if ( !hooks || !( "set" in hooks ) ||
                   ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
   
                   if ( isCustomProp ) {
                       style.setProperty( name, value );
                   } else {
                       style[ name ] = value;
                   }
               }
   
           } else {
   
               // If a hook was provided get the non-computed value from there
               if ( hooks && "get" in hooks &&
                   ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
   
                   return ret;
               }
   
               // Otherwise just get the value from the style object
               return style[ name ];
           }
       },
   
       css: function( elem, name, extra, styles ) {
           var val, num, hooks,
               origName = jQuery.camelCase( name ),
               isCustomProp = rcustomProp.test( name );
   
           // Make sure that we're working with the right name. We don't
           // want to modify the value if it is a CSS custom property
           // since they are user-defined.
           if ( !isCustomProp ) {
               name = finalPropName( origName );
           }
   
           // Try prefixed name followed by the unprefixed name
           hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
   
           // If a hook was provided get the computed value from there
           if ( hooks && "get" in hooks ) {
               val = hooks.get( elem, true, extra );
           }
   
           // Otherwise, if a way to get the computed value exists, use that
           if ( val === undefined ) {
               val = curCSS( elem, name, styles );
           }
   
           // Convert "normal" to computed value
           if ( val === "normal" && name in cssNormalTransform ) {
               val = cssNormalTransform[ name ];
           }
   
           // Make numeric if forced or a qualifier was provided and val looks numeric
           if ( extra === "" || extra ) {
               num = parseFloat( val );
               return extra === true || isFinite( num ) ? num || 0 : val;
           }
   
           return val;
       }
   } );
   
   jQuery.each( [ "height", "width" ], function( i, name ) {
       jQuery.cssHooks[ name ] = {
           get: function( elem, computed, extra ) {
               if ( computed ) {
   
                   // Certain elements can have dimension info if we invisibly show them
                   // but it must have a current display style that would benefit
                   return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
   
                       // Support: Safari 8+
                       // Table columns in Safari have non-zero offsetWidth & zero
                       // getBoundingClientRect().width unless display is changed.
                       // Support: IE <=11 only
                       // Running getBoundingClientRect on a disconnected node
                       // in IE throws an error.
                       ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
                           swap( elem, cssShow, function() {
                               return getWidthOrHeight( elem, name, extra );
                           } ) :
                           getWidthOrHeight( elem, name, extra );
               }
           },
   
           set: function( elem, value, extra ) {
               var matches,
                   styles = extra && getStyles( elem ),
                   subtract = extra && augmentWidthOrHeight(
                       elem,
                       name,
                       extra,
                       jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
                       styles
                   );
   
               // Convert to pixels if value adjustment is needed
               if ( subtract && ( matches = rcssNum.exec( value ) ) &&
                   ( matches[ 3 ] || "px" ) !== "px" ) {
   
                   elem.style[ name ] = value;
                   value = jQuery.css( elem, name );
               }
   
               return setPositiveNumber( elem, value, subtract );
           }
       };
   } );
   
   jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
       function( elem, computed ) {
           if ( computed ) {
               return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
                   elem.getBoundingClientRect().left -
                       swap( elem, { marginLeft: 0 }, function() {
                           return elem.getBoundingClientRect().left;
                       } )
                   ) + "px";
           }
       }
   );
   
   // These hooks are used by animate to expand properties
   jQuery.each( {
       margin: "",
       padding: "",
       border: "Width"
   }, function( prefix, suffix ) {
       jQuery.cssHooks[ prefix + suffix ] = {
           expand: function( value ) {
               var i = 0,
                   expanded = {},
   
                   // Assumes a single number if not a string
                   parts = typeof value === "string" ? value.split( " " ) : [ value ];
   
               for ( ; i < 4; i++ ) {
                   expanded[ prefix + cssExpand[ i ] + suffix ] =
                       parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
               }
   
               return expanded;
           }
       };
   
       if ( !rmargin.test( prefix ) ) {
           jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
       }
   } );
   
   jQuery.fn.extend( {
       css: function( name, value ) {
           return access( this, function( elem, name, value ) {
               var styles, len,
                   map = {},
                   i = 0;
   
               if ( Array.isArray( name ) ) {
                   styles = getStyles( elem );
                   len = name.length;
   
                   for ( ; i < len; i++ ) {
                       map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
                   }
   
                   return map;
               }
   
               return value !== undefined ?
                   jQuery.style( elem, name, value ) :
                   jQuery.css( elem, name );
           }, name, value, arguments.length > 1 );
       }
   } );
   
   
   function Tween( elem, options, prop, end, easing ) {
       return new Tween.prototype.init( elem, options, prop, end, easing );
   }
   jQuery.Tween = Tween;
   
   Tween.prototype = {
       constructor: Tween,
       init: function( elem, options, prop, end, easing, unit ) {
           this.elem = elem;
           this.prop = prop;
           this.easing = easing || jQuery.easing._default;
           this.options = options;
           this.start = this.now = this.cur();
           this.end = end;
           this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
       },
       cur: function() {
           var hooks = Tween.propHooks[ this.prop ];
   
           return hooks && hooks.get ?
               hooks.get( this ) :
               Tween.propHooks._default.get( this );
       },
       run: function( percent ) {
           var eased,
               hooks = Tween.propHooks[ this.prop ];
   
           if ( this.options.duration ) {
               this.pos = eased = jQuery.easing[ this.easing ](
                   percent, this.options.duration * percent, 0, 1, this.options.duration
               );
           } else {
               this.pos = eased = percent;
           }
           this.now = ( this.end - this.start ) * eased + this.start;
   
           if ( this.options.step ) {
               this.options.step.call( this.elem, this.now, this );
           }
   
           if ( hooks && hooks.set ) {
               hooks.set( this );
           } else {
               Tween.propHooks._default.set( this );
           }
           return this;
       }
   };
   
   Tween.prototype.init.prototype = Tween.prototype;
   
   Tween.propHooks = {
       _default: {
           get: function( tween ) {
               var result;
   
               // Use a property on the element directly when it is not a DOM element,
               // or when there is no matching style property that exists.
               if ( tween.elem.nodeType !== 1 ||
                   tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
                   return tween.elem[ tween.prop ];
               }
   
               // Passing an empty string as a 3rd parameter to .css will automatically
               // attempt a parseFloat and fallback to a string if the parse fails.
               // Simple values such as "10px" are parsed to Float;
               // complex values such as "rotate(1rad)" are returned as-is.
               result = jQuery.css( tween.elem, tween.prop, "" );
   
               // Empty strings, null, undefined and "auto" are converted to 0.
               return !result || result === "auto" ? 0 : result;
           },
           set: function( tween ) {
   
               // Use step hook for back compat.
               // Use cssHook if its there.
               // Use .style if available and use plain properties where available.
               if ( jQuery.fx.step[ tween.prop ] ) {
                   jQuery.fx.step[ tween.prop ]( tween );
               } else if ( tween.elem.nodeType === 1 &&
                   ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
                       jQuery.cssHooks[ tween.prop ] ) ) {
                   jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
               } else {
                   tween.elem[ tween.prop ] = tween.now;
               }
           }
       }
   };
   
   // Support: IE <=9 only
   // Panic based approach to setting things on disconnected nodes
   Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
       set: function( tween ) {
           if ( tween.elem.nodeType && tween.elem.parentNode ) {
               tween.elem[ tween.prop ] = tween.now;
           }
       }
   };
   
   jQuery.easing = {
       linear: function( p ) {
           return p;
       },
       swing: function( p ) {
           return 0.5 - Math.cos( p * Math.PI ) / 2;
       },
       _default: "swing"
   };
   
   jQuery.fx = Tween.prototype.init;
   
   // Back compat <1.8 extension point
   jQuery.fx.step = {};
   
   
   
   
   var
       fxNow, inProgress,
       rfxtypes = /^(?:toggle|show|hide)$/,
       rrun = /queueHooks$/;
   
   function schedule() {
       if ( inProgress ) {
           if ( document.hidden === false && window.requestAnimationFrame ) {
               window.requestAnimationFrame( schedule );
           } else {
               window.setTimeout( schedule, jQuery.fx.interval );
           }
   
           jQuery.fx.tick();
       }
   }
   
   // Animations created synchronously will run synchronously
   function createFxNow() {
       window.setTimeout( function() {
           fxNow = undefined;
       } );
       return ( fxNow = jQuery.now() );
   }
   
   // Generate parameters to create a standard animation
   function genFx( type, includeWidth ) {
       var which,
           i = 0,
           attrs = { height: type };
   
       // If we include width, step value is 1 to do all cssExpand values,
       // otherwise step value is 2 to skip over Left and Right
       includeWidth = includeWidth ? 1 : 0;
       for ( ; i < 4; i += 2 - includeWidth ) {
           which = cssExpand[ i ];
           attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
       }
   
       if ( includeWidth ) {
           attrs.opacity = attrs.width = type;
       }
   
       return attrs;
   }
   
   function createTween( value, prop, animation ) {
       var tween,
           collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
           index = 0,
           length = collection.length;
       for ( ; index < length; index++ ) {
           if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
   
               // We're done with this property
               return tween;
           }
       }
   }
   
   function defaultPrefilter( elem, props, opts ) {
       var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
           isBox = "width" in props || "height" in props,
           anim = this,
           orig = {},
           style = elem.style,
           hidden = elem.nodeType && isHiddenWithinTree( elem ),
           dataShow = dataPriv.get( elem, "fxshow" );
   
       // Queue-skipping animations hijack the fx hooks
       if ( !opts.queue ) {
           hooks = jQuery._queueHooks( elem, "fx" );
           if ( hooks.unqueued == null ) {
               hooks.unqueued = 0;
               oldfire = hooks.empty.fire;
               hooks.empty.fire = function() {
                   if ( !hooks.unqueued ) {
                       oldfire();
                   }
               };
           }
           hooks.unqueued++;
   
           anim.always( function() {
   
               // Ensure the complete handler is called before this completes
               anim.always( function() {
                   hooks.unqueued--;
                   if ( !jQuery.queue( elem, "fx" ).length ) {
                       hooks.empty.fire();
                   }
               } );
           } );
       }
   
       // Detect show/hide animations
       for ( prop in props ) {
           value = props[ prop ];
           if ( rfxtypes.test( value ) ) {
               delete props[ prop ];
               toggle = toggle || value === "toggle";
               if ( value === ( hidden ? "hide" : "show" ) ) {
   
                   // Pretend to be hidden if this is a "show" and
                   // there is still data from a stopped show/hide
                   if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
                       hidden = true;
   
                   // Ignore all other no-op show/hide data
                   } else {
                       continue;
                   }
               }
               orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
           }
       }
   
       // Bail out if this is a no-op like .hide().hide()
       propTween = !jQuery.isEmptyObject( props );
       if ( !propTween && jQuery.isEmptyObject( orig ) ) {
           return;
       }
   
       // Restrict "overflow" and "display" styles during box animations
       if ( isBox && elem.nodeType === 1 ) {
   
           // Support: IE <=9 - 11, Edge 12 - 13
           // Record all 3 overflow attributes because IE does not infer the shorthand
           // from identically-valued overflowX and overflowY
           opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
   
           // Identify a display type, preferring old show/hide data over the CSS cascade
           restoreDisplay = dataShow && dataShow.display;
           if ( restoreDisplay == null ) {
               restoreDisplay = dataPriv.get( elem, "display" );
           }
           display = jQuery.css( elem, "display" );
           if ( display === "none" ) {
               if ( restoreDisplay ) {
                   display = restoreDisplay;
               } else {
   
                   // Get nonempty value(s) by temporarily forcing visibility
                   showHide( [ elem ], true );
                   restoreDisplay = elem.style.display || restoreDisplay;
                   display = jQuery.css( elem, "display" );
                   showHide( [ elem ] );
               }
           }
   
           // Animate inline elements as inline-block
           if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
               if ( jQuery.css( elem, "float" ) === "none" ) {
   
                   // Restore the original display value at the end of pure show/hide animations
                   if ( !propTween ) {
                       anim.done( function() {
                           style.display = restoreDisplay;
                       } );
                       if ( restoreDisplay == null ) {
                           display = style.display;
                           restoreDisplay = display === "none" ? "" : display;
                       }
                   }
                   style.display = "inline-block";
               }
           }
       }
   
       if ( opts.overflow ) {
           style.overflow = "hidden";
           anim.always( function() {
               style.overflow = opts.overflow[ 0 ];
               style.overflowX = opts.overflow[ 1 ];
               style.overflowY = opts.overflow[ 2 ];
           } );
       }
   
       // Implement show/hide animations
       propTween = false;
       for ( prop in orig ) {
   
           // General show/hide setup for this element animation
           if ( !propTween ) {
               if ( dataShow ) {
                   if ( "hidden" in dataShow ) {
                       hidden = dataShow.hidden;
                   }
               } else {
                   dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
               }
   
               // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
               if ( toggle ) {
                   dataShow.hidden = !hidden;
               }
   
               // Show elements before animating them
               if ( hidden ) {
                   showHide( [ elem ], true );
               }
   
               /* eslint-disable no-loop-func */
   
               anim.done( function() {
   
               /* eslint-enable no-loop-func */
   
                   // The final step of a "hide" animation is actually hiding the element
                   if ( !hidden ) {
                       showHide( [ elem ] );
                   }
                   dataPriv.remove( elem, "fxshow" );
                   for ( prop in orig ) {
                       jQuery.style( elem, prop, orig[ prop ] );
                   }
               } );
           }
   
           // Per-property setup
           propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
           if ( !( prop in dataShow ) ) {
               dataShow[ prop ] = propTween.start;
               if ( hidden ) {
                   propTween.end = propTween.start;
                   propTween.start = 0;
               }
           }
       }
   }
   
   function propFilter( props, specialEasing ) {
       var index, name, easing, value, hooks;
   
       // camelCase, specialEasing and expand cssHook pass
       for ( index in props ) {
           name = jQuery.camelCase( index );
           easing = specialEasing[ name ];
           value = props[ index ];
           if ( Array.isArray( value ) ) {
               easing = value[ 1 ];
               value = props[ index ] = value[ 0 ];
           }
   
           if ( index !== name ) {
               props[ name ] = value;
               delete props[ index ];
           }
   
           hooks = jQuery.cssHooks[ name ];
           if ( hooks && "expand" in hooks ) {
               value = hooks.expand( value );
               delete props[ name ];
   
               // Not quite $.extend, this won't overwrite existing keys.
               // Reusing 'index' because we have the correct "name"
               for ( index in value ) {
                   if ( !( index in props ) ) {
                       props[ index ] = value[ index ];
                       specialEasing[ index ] = easing;
                   }
               }
           } else {
               specialEasing[ name ] = easing;
           }
       }
   }
   
   function Animation( elem, properties, options ) {
       var result,
           stopped,
           index = 0,
           length = Animation.prefilters.length,
           deferred = jQuery.Deferred().always( function() {
   
               // Don't match elem in the :animated selector
               delete tick.elem;
           } ),
           tick = function() {
               if ( stopped ) {
                   return false;
               }
               var currentTime = fxNow || createFxNow(),
                   remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
   
                   // Support: Android 2.3 only
                   // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
                   temp = remaining / animation.duration || 0,
                   percent = 1 - temp,
                   index = 0,
                   length = animation.tweens.length;
   
               for ( ; index < length; index++ ) {
                   animation.tweens[ index ].run( percent );
               }
   
               deferred.notifyWith( elem, [ animation, percent, remaining ] );
   
               // If there's more to do, yield
               if ( percent < 1 && length ) {
                   return remaining;
               }
   
               // If this was an empty animation, synthesize a final progress notification
               if ( !length ) {
                   deferred.notifyWith( elem, [ animation, 1, 0 ] );
               }
   
               // Resolve the animation and report its conclusion
               deferred.resolveWith( elem, [ animation ] );
               return false;
           },
           animation = deferred.promise( {
               elem: elem,
               props: jQuery.extend( {}, properties ),
               opts: jQuery.extend( true, {
                   specialEasing: {},
                   easing: jQuery.easing._default
               }, options ),
               originalProperties: properties,
               originalOptions: options,
               startTime: fxNow || createFxNow(),
               duration: options.duration,
               tweens: [],
               createTween: function( prop, end ) {
                   var tween = jQuery.Tween( elem, animation.opts, prop, end,
                           animation.opts.specialEasing[ prop ] || animation.opts.easing );
                   animation.tweens.push( tween );
                   return tween;
               },
               stop: function( gotoEnd ) {
                   var index = 0,
   
                       // If we are going to the end, we want to run all the tweens
                       // otherwise we skip this part
                       length = gotoEnd ? animation.tweens.length : 0;
                   if ( stopped ) {
                       return this;
                   }
                   stopped = true;
                   for ( ; index < length; index++ ) {
                       animation.tweens[ index ].run( 1 );
                   }
   
                   // Resolve when we played the last frame; otherwise, reject
                   if ( gotoEnd ) {
                       deferred.notifyWith( elem, [ animation, 1, 0 ] );
                       deferred.resolveWith( elem, [ animation, gotoEnd ] );
                   } else {
                       deferred.rejectWith( elem, [ animation, gotoEnd ] );
                   }
                   return this;
               }
           } ),
           props = animation.props;
   
       propFilter( props, animation.opts.specialEasing );
   
       for ( ; index < length; index++ ) {
           result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
           if ( result ) {
               if ( jQuery.isFunction( result.stop ) ) {
                   jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
                       jQuery.proxy( result.stop, result );
               }
               return result;
           }
       }
   
       jQuery.map( props, createTween, animation );
   
       if ( jQuery.isFunction( animation.opts.start ) ) {
           animation.opts.start.call( elem, animation );
       }
   
       // Attach callbacks from options
       animation
           .progress( animation.opts.progress )
           .done( animation.opts.done, animation.opts.complete )
           .fail( animation.opts.fail )
           .always( animation.opts.always );
   
       jQuery.fx.timer(
           jQuery.extend( tick, {
               elem: elem,
               anim: animation,
               queue: animation.opts.queue
           } )
       );
   
       return animation;
   }
   
   jQuery.Animation = jQuery.extend( Animation, {
   
       tweeners: {
           "*": [ function( prop, value ) {
               var tween = this.createTween( prop, value );
               adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
               return tween;
           } ]
       },
   
       tweener: function( props, callback ) {
           if ( jQuery.isFunction( props ) ) {
               callback = props;
               props = [ "*" ];
           } else {
               props = props.match( rnothtmlwhite );
           }
   
           var prop,
               index = 0,
               length = props.length;
   
           for ( ; index < length; index++ ) {
               prop = props[ index ];
               Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
               Animation.tweeners[ prop ].unshift( callback );
           }
       },
   
       prefilters: [ defaultPrefilter ],
   
       prefilter: function( callback, prepend ) {
           if ( prepend ) {
               Animation.prefilters.unshift( callback );
           } else {
               Animation.prefilters.push( callback );
           }
       }
   } );
   
   jQuery.speed = function( speed, easing, fn ) {
       var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
           complete: fn || !fn && easing ||
               jQuery.isFunction( speed ) && speed,
           duration: speed,
           easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
       };
   
       // Go to the end state if fx are off
       if ( jQuery.fx.off ) {
           opt.duration = 0;
   
       } else {
           if ( typeof opt.duration !== "number" ) {
               if ( opt.duration in jQuery.fx.speeds ) {
                   opt.duration = jQuery.fx.speeds[ opt.duration ];
   
               } else {
                   opt.duration = jQuery.fx.speeds._default;
               }
           }
       }
   
       // Normalize opt.queue - true/undefined/null -> "fx"
       if ( opt.queue == null || opt.queue === true ) {
           opt.queue = "fx";
       }
   
       // Queueing
       opt.old = opt.complete;
   
       opt.complete = function() {
           if ( jQuery.isFunction( opt.old ) ) {
               opt.old.call( this );
           }
   
           if ( opt.queue ) {
               jQuery.dequeue( this, opt.queue );
           }
       };
   
       return opt;
   };
   
   jQuery.fn.extend( {
       fadeTo: function( speed, to, easing, callback ) {
   
           // Show any hidden elements after setting opacity to 0
           return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
   
               // Animate to the value specified
               .end().animate( { opacity: to }, speed, easing, callback );
       },
       animate: function( prop, speed, easing, callback ) {
           var empty = jQuery.isEmptyObject( prop ),
               optall = jQuery.speed( speed, easing, callback ),
               doAnimation = function() {
   
                   // Operate on a copy of prop so per-property easing won't be lost
                   var anim = Animation( this, jQuery.extend( {}, prop ), optall );
   
                   // Empty animations, or finishing resolves immediately
                   if ( empty || dataPriv.get( this, "finish" ) ) {
                       anim.stop( true );
                   }
               };
               doAnimation.finish = doAnimation;
   
           return empty || optall.queue === false ?
               this.each( doAnimation ) :
               this.queue( optall.queue, doAnimation );
       },
       stop: function( type, clearQueue, gotoEnd ) {
           var stopQueue = function( hooks ) {
               var stop = hooks.stop;
               delete hooks.stop;
               stop( gotoEnd );
           };
   
           if ( typeof type !== "string" ) {
               gotoEnd = clearQueue;
               clearQueue = type;
               type = undefined;
           }
           if ( clearQueue && type !== false ) {
               this.queue( type || "fx", [] );
           }
   
           return this.each( function() {
               var dequeue = true,
                   index = type != null && type + "queueHooks",
                   timers = jQuery.timers,
                   data = dataPriv.get( this );
   
               if ( index ) {
                   if ( data[ index ] && data[ index ].stop ) {
                       stopQueue( data[ index ] );
                   }
               } else {
                   for ( index in data ) {
                       if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
                           stopQueue( data[ index ] );
                       }
                   }
               }
   
               for ( index = timers.length; index--; ) {
                   if ( timers[ index ].elem === this &&
                       ( type == null || timers[ index ].queue === type ) ) {
   
                       timers[ index ].anim.stop( gotoEnd );
                       dequeue = false;
                       timers.splice( index, 1 );
                   }
               }
   
               // Start the next in the queue if the last step wasn't forced.
               // Timers currently will call their complete callbacks, which
               // will dequeue but only if they were gotoEnd.
               if ( dequeue || !gotoEnd ) {
                   jQuery.dequeue( this, type );
               }
           } );
       },
       finish: function( type ) {
           if ( type !== false ) {
               type = type || "fx";
           }
           return this.each( function() {
               var index,
                   data = dataPriv.get( this ),
                   queue = data[ type + "queue" ],
                   hooks = data[ type + "queueHooks" ],
                   timers = jQuery.timers,
                   length = queue ? queue.length : 0;
   
               // Enable finishing flag on private data
               data.finish = true;
   
               // Empty the queue first
               jQuery.queue( this, type, [] );
   
               if ( hooks && hooks.stop ) {
                   hooks.stop.call( this, true );
               }
   
               // Look for any active animations, and finish them
               for ( index = timers.length; index--; ) {
                   if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
                       timers[ index ].anim.stop( true );
                       timers.splice( index, 1 );
                   }
               }
   
               // Look for any animations in the old queue and finish them
               for ( index = 0; index < length; index++ ) {
                   if ( queue[ index ] && queue[ index ].finish ) {
                       queue[ index ].finish.call( this );
                   }
               }
   
               // Turn off finishing flag
               delete data.finish;
           } );
       }
   } );
   
   jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
       var cssFn = jQuery.fn[ name ];
       jQuery.fn[ name ] = function( speed, easing, callback ) {
           return speed == null || typeof speed === "boolean" ?
               cssFn.apply( this, arguments ) :
               this.animate( genFx( name, true ), speed, easing, callback );
       };
   } );
   
   // Generate shortcuts for custom animations
   jQuery.each( {
       slideDown: genFx( "show" ),
       slideUp: genFx( "hide" ),
       slideToggle: genFx( "toggle" ),
       fadeIn: { opacity: "show" },
       fadeOut: { opacity: "hide" },
       fadeToggle: { opacity: "toggle" }
   }, function( name, props ) {
       jQuery.fn[ name ] = function( speed, easing, callback ) {
           return this.animate( props, speed, easing, callback );
       };
   } );
   
   jQuery.timers = [];
   jQuery.fx.tick = function() {
       var timer,
           i = 0,
           timers = jQuery.timers;
   
       fxNow = jQuery.now();
   
       for ( ; i < timers.length; i++ ) {
           timer = timers[ i ];
   
           // Run the timer and safely remove it when done (allowing for external removal)
           if ( !timer() && timers[ i ] === timer ) {
               timers.splice( i--, 1 );
           }
       }
   
       if ( !timers.length ) {
           jQuery.fx.stop();
       }
       fxNow = undefined;
   };
   
   jQuery.fx.timer = function( timer ) {
       jQuery.timers.push( timer );
       jQuery.fx.start();
   };
   
   jQuery.fx.interval = 13;
   jQuery.fx.start = function() {
       if ( inProgress ) {
           return;
       }
   
       inProgress = true;
       schedule();
   };
   
   jQuery.fx.stop = function() {
       inProgress = null;
   };
   
   jQuery.fx.speeds = {
       slow: 600,
       fast: 200,
   
       // Default speed
       _default: 400
   };
   
   
   // Based off of the plugin by Clint Helfers, with permission.
   // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
   jQuery.fn.delay = function( time, type ) {
       time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
       type = type || "fx";
   
       return this.queue( type, function( next, hooks ) {
           var timeout = window.setTimeout( next, time );
           hooks.stop = function() {
               window.clearTimeout( timeout );
           };
       } );
   };
   
   
   ( function() {
       var input = document.createElement( "input" ),
           select = document.createElement( "select" ),
           opt = select.appendChild( document.createElement( "option" ) );
   
       input.type = "checkbox";
   
       // Support: Android <=4.3 only
       // Default value for a checkbox should be "on"
       support.checkOn = input.value !== "";
   
       // Support: IE <=11 only
       // Must access selectedIndex to make default options select
       support.optSelected = opt.selected;
   
       // Support: IE <=11 only
       // An input loses its value after becoming a radio
       input = document.createElement( "input" );
       input.value = "t";
       input.type = "radio";
       support.radioValue = input.value === "t";
   } )();
   
   
   var boolHook,
       attrHandle = jQuery.expr.attrHandle;
   
   jQuery.fn.extend( {
       attr: function( name, value ) {
           return access( this, jQuery.attr, name, value, arguments.length > 1 );
       },
   
       removeAttr: function( name ) {
           return this.each( function() {
               jQuery.removeAttr( this, name );
           } );
       }
   } );
   
   jQuery.extend( {
       attr: function( elem, name, value ) {
           var ret, hooks,
               nType = elem.nodeType;
   
           // Don't get/set attributes on text, comment and attribute nodes
           if ( nType === 3 || nType === 8 || nType === 2 ) {
               return;
           }
   
           // Fallback to prop when attributes are not supported
           if ( typeof elem.getAttribute === "undefined" ) {
               return jQuery.prop( elem, name, value );
           }
   
           // Attribute hooks are determined by the lowercase version
           // Grab necessary hook if one is defined
           if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
               hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
                   ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
           }
   
           if ( value !== undefined ) {
               if ( value === null ) {
                   jQuery.removeAttr( elem, name );
                   return;
               }
   
               if ( hooks && "set" in hooks &&
                   ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
                   return ret;
               }
   
               elem.setAttribute( name, value + "" );
               return value;
           }
   
           if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
               return ret;
           }
   
           ret = jQuery.find.attr( elem, name );
   
           // Non-existent attributes return null, we normalize to undefined
           return ret == null ? undefined : ret;
       },
   
       attrHooks: {
           type: {
               set: function( elem, value ) {
                   if ( !support.radioValue && value === "radio" &&
                       nodeName( elem, "input" ) ) {
                       var val = elem.value;
                       elem.setAttribute( "type", value );
                       if ( val ) {
                           elem.value = val;
                       }
                       return value;
                   }
               }
           }
       },
   
       removeAttr: function( elem, value ) {
           var name,
               i = 0,
   
               // Attribute names can contain non-HTML whitespace characters
               // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
               attrNames = value && value.match( rnothtmlwhite );
   
           if ( attrNames && elem.nodeType === 1 ) {
               while ( ( name = attrNames[ i++ ] ) ) {
                   elem.removeAttribute( name );
               }
           }
       }
   } );
   
   // Hooks for boolean attributes
   boolHook = {
       set: function( elem, value, name ) {
           if ( value === false ) {
   
               // Remove boolean attributes when set to false
               jQuery.removeAttr( elem, name );
           } else {
               elem.setAttribute( name, name );
           }
           return name;
       }
   };
   
   jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
       var getter = attrHandle[ name ] || jQuery.find.attr;
   
       attrHandle[ name ] = function( elem, name, isXML ) {
           var ret, handle,
               lowercaseName = name.toLowerCase();
   
           if ( !isXML ) {
   
               // Avoid an infinite loop by temporarily removing this function from the getter
               handle = attrHandle[ lowercaseName ];
               attrHandle[ lowercaseName ] = ret;
               ret = getter( elem, name, isXML ) != null ?
                   lowercaseName :
                   null;
               attrHandle[ lowercaseName ] = handle;
           }
           return ret;
       };
   } );
   
   
   
   
   var rfocusable = /^(?:input|select|textarea|button)$/i,
       rclickable = /^(?:a|area)$/i;
   
   jQuery.fn.extend( {
       prop: function( name, value ) {
           return access( this, jQuery.prop, name, value, arguments.length > 1 );
       },
   
       removeProp: function( name ) {
           return this.each( function() {
               delete this[ jQuery.propFix[ name ] || name ];
           } );
       }
   } );
   
   jQuery.extend( {
       prop: function( elem, name, value ) {
           var ret, hooks,
               nType = elem.nodeType;
   
           // Don't get/set properties on text, comment and attribute nodes
           if ( nType === 3 || nType === 8 || nType === 2 ) {
               return;
           }
   
           if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
   
               // Fix name and attach hooks
               name = jQuery.propFix[ name ] || name;
               hooks = jQuery.propHooks[ name ];
           }
   
           if ( value !== undefined ) {
               if ( hooks && "set" in hooks &&
                   ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
                   return ret;
               }
   
               return ( elem[ name ] = value );
           }
   
           if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
               return ret;
           }
   
           return elem[ name ];
       },
   
       propHooks: {
           tabIndex: {
               get: function( elem ) {
   
                   // Support: IE <=9 - 11 only
                   // elem.tabIndex doesn't always return the
                   // correct value when it hasn't been explicitly set
                   // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
                   // Use proper attribute retrieval(#12072)
                   var tabindex = jQuery.find.attr( elem, "tabindex" );
   
                   if ( tabindex ) {
                       return parseInt( tabindex, 10 );
                   }
   
                   if (
                       rfocusable.test( elem.nodeName ) ||
                       rclickable.test( elem.nodeName ) &&
                       elem.href
                   ) {
                       return 0;
                   }
   
                   return -1;
               }
           }
       },
   
       propFix: {
           "for": "htmlFor",
           "class": "className"
       }
   } );
   
   // Support: IE <=11 only
   // Accessing the selectedIndex property
   // forces the browser to respect setting selected
   // on the option
   // The getter ensures a default option is selected
   // when in an optgroup
   // eslint rule "no-unused-expressions" is disabled for this code
   // since it considers such accessions noop
   if ( !support.optSelected ) {
       jQuery.propHooks.selected = {
           get: function( elem ) {
   
               /* eslint no-unused-expressions: "off" */
   
               var parent = elem.parentNode;
               if ( parent && parent.parentNode ) {
                   parent.parentNode.selectedIndex;
               }
               return null;
           },
           set: function( elem ) {
   
               /* eslint no-unused-expressions: "off" */
   
               var parent = elem.parentNode;
               if ( parent ) {
                   parent.selectedIndex;
   
                   if ( parent.parentNode ) {
                       parent.parentNode.selectedIndex;
                   }
               }
           }
       };
   }
   
   jQuery.each( [
       "tabIndex",
       "readOnly",
       "maxLength",
       "cellSpacing",
       "cellPadding",
       "rowSpan",
       "colSpan",
       "useMap",
       "frameBorder",
       "contentEditable"
   ], function() {
       jQuery.propFix[ this.toLowerCase() ] = this;
   } );
   
   
   
   
       // Strip and collapse whitespace according to HTML spec
       // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
       function stripAndCollapse( value ) {
           var tokens = value.match( rnothtmlwhite ) || [];
           return tokens.join( " " );
       }
   
   
   function getClass( elem ) {
       return elem.getAttribute && elem.getAttribute( "class" ) || "";
   }
   
   jQuery.fn.extend( {
       addClass: function( value ) {
           var classes, elem, cur, curValue, clazz, j, finalValue,
               i = 0;
   
           if ( jQuery.isFunction( value ) ) {
               return this.each( function( j ) {
                   jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
               } );
           }
   
           if ( typeof value === "string" && value ) {
               classes = value.match( rnothtmlwhite ) || [];
   
               while ( ( elem = this[ i++ ] ) ) {
                   curValue = getClass( elem );
                   cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
   
                   if ( cur ) {
                       j = 0;
                       while ( ( clazz = classes[ j++ ] ) ) {
                           if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                               cur += clazz + " ";
                           }
                       }
   
                       // Only assign if different to avoid unneeded rendering.
                       finalValue = stripAndCollapse( cur );
                       if ( curValue !== finalValue ) {
                           elem.setAttribute( "class", finalValue );
                       }
                   }
               }
           }
   
           return this;
       },
   
       removeClass: function( value ) {
           var classes, elem, cur, curValue, clazz, j, finalValue,
               i = 0;
   
           if ( jQuery.isFunction( value ) ) {
               return this.each( function( j ) {
                   jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
               } );
           }
   
           if ( !arguments.length ) {
               return this.attr( "class", "" );
           }
   
           if ( typeof value === "string" && value ) {
               classes = value.match( rnothtmlwhite ) || [];
   
               while ( ( elem = this[ i++ ] ) ) {
                   curValue = getClass( elem );
   
                   // This expression is here for better compressibility (see addClass)
                   cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
   
                   if ( cur ) {
                       j = 0;
                       while ( ( clazz = classes[ j++ ] ) ) {
   
                           // Remove *all* instances
                           while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
                               cur = cur.replace( " " + clazz + " ", " " );
                           }
                       }
   
                       // Only assign if different to avoid unneeded rendering.
                       finalValue = stripAndCollapse( cur );
                       if ( curValue !== finalValue ) {
                           elem.setAttribute( "class", finalValue );
                       }
                   }
               }
           }
   
           return this;
       },
   
       toggleClass: function( value, stateVal ) {
           var type = typeof value;
   
           if ( typeof stateVal === "boolean" && type === "string" ) {
               return stateVal ? this.addClass( value ) : this.removeClass( value );
           }
   
           if ( jQuery.isFunction( value ) ) {
               return this.each( function( i ) {
                   jQuery( this ).toggleClass(
                       value.call( this, i, getClass( this ), stateVal ),
                       stateVal
                   );
               } );
           }
   
           return this.each( function() {
               var className, i, self, classNames;
   
               if ( type === "string" ) {
   
                   // Toggle individual class names
                   i = 0;
                   self = jQuery( this );
                   classNames = value.match( rnothtmlwhite ) || [];
   
                   while ( ( className = classNames[ i++ ] ) ) {
   
                       // Check each className given, space separated list
                       if ( self.hasClass( className ) ) {
                           self.removeClass( className );
                       } else {
                           self.addClass( className );
                       }
                   }
   
               // Toggle whole class name
               } else if ( value === undefined || type === "boolean" ) {
                   className = getClass( this );
                   if ( className ) {
   
                       // Store className if set
                       dataPriv.set( this, "__className__", className );
                   }
   
                   // If the element has a class name or if we're passed `false`,
                   // then remove the whole classname (if there was one, the above saved it).
                   // Otherwise bring back whatever was previously saved (if anything),
                   // falling back to the empty string if nothing was stored.
                   if ( this.setAttribute ) {
                       this.setAttribute( "class",
                           className || value === false ?
                           "" :
                           dataPriv.get( this, "__className__" ) || ""
                       );
                   }
               }
           } );
       },
   
       hasClass: function( selector ) {
           var className, elem,
               i = 0;
   
           className = " " + selector + " ";
           while ( ( elem = this[ i++ ] ) ) {
               if ( elem.nodeType === 1 &&
                   ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
                       return true;
               }
           }
   
           return false;
       }
   } );
   
   
   
   
   var rreturn = /\r/g;
   
   jQuery.fn.extend( {
       val: function( value ) {
           var hooks, ret, isFunction,
               elem = this[ 0 ];
   
           if ( !arguments.length ) {
               if ( elem ) {
                   hooks = jQuery.valHooks[ elem.type ] ||
                       jQuery.valHooks[ elem.nodeName.toLowerCase() ];
   
                   if ( hooks &&
                       "get" in hooks &&
                       ( ret = hooks.get( elem, "value" ) ) !== undefined
                   ) {
                       return ret;
                   }
   
                   ret = elem.value;
   
                   // Handle most common string cases
                   if ( typeof ret === "string" ) {
                       return ret.replace( rreturn, "" );
                   }
   
                   // Handle cases where value is null/undef or number
                   return ret == null ? "" : ret;
               }
   
               return;
           }
   
           isFunction = jQuery.isFunction( value );
   
           return this.each( function( i ) {
               var val;
   
               if ( this.nodeType !== 1 ) {
                   return;
               }
   
               if ( isFunction ) {
                   val = value.call( this, i, jQuery( this ).val() );
               } else {
                   val = value;
               }
   
               // Treat null/undefined as ""; convert numbers to string
               if ( val == null ) {
                   val = "";
   
               } else if ( typeof val === "number" ) {
                   val += "";
   
               } else if ( Array.isArray( val ) ) {
                   val = jQuery.map( val, function( value ) {
                       return value == null ? "" : value + "";
                   } );
               }
   
               hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
   
               // If set returns undefined, fall back to normal setting
               if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
                   this.value = val;
               }
           } );
       }
   } );
   
   jQuery.extend( {
       valHooks: {
           option: {
               get: function( elem ) {
   
                   var val = jQuery.find.attr( elem, "value" );
                   return val != null ?
                       val :
   
                       // Support: IE <=10 - 11 only
                       // option.text throws exceptions (#14686, #14858)
                       // Strip and collapse whitespace
                       // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
                       stripAndCollapse( jQuery.text( elem ) );
               }
           },
           select: {
               get: function( elem ) {
                   var value, option, i,
                       options = elem.options,
                       index = elem.selectedIndex,
                       one = elem.type === "select-one",
                       values = one ? null : [],
                       max = one ? index + 1 : options.length;
   
                   if ( index < 0 ) {
                       i = max;
   
                   } else {
                       i = one ? index : 0;
                   }
   
                   // Loop through all the selected options
                   for ( ; i < max; i++ ) {
                       option = options[ i ];
   
                       // Support: IE <=9 only
                       // IE8-9 doesn't update selected after form reset (#2551)
                       if ( ( option.selected || i === index ) &&
   
                               // Don't return options that are disabled or in a disabled optgroup
                               !option.disabled &&
                               ( !option.parentNode.disabled ||
                                   !nodeName( option.parentNode, "optgroup" ) ) ) {
   
                           // Get the specific value for the option
                           value = jQuery( option ).val();
   
                           // We don't need an array for one selects
                           if ( one ) {
                               return value;
                           }
   
                           // Multi-Selects return an array
                           values.push( value );
                       }
                   }
   
                   return values;
               },
   
               set: function( elem, value ) {
                   var optionSet, option,
                       options = elem.options,
                       values = jQuery.makeArray( value ),
                       i = options.length;
   
                   while ( i-- ) {
                       option = options[ i ];
   
                       /* eslint-disable no-cond-assign */
   
                       if ( option.selected =
                           jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
                       ) {
                           optionSet = true;
                       }
   
                       /* eslint-enable no-cond-assign */
                   }
   
                   // Force browsers to behave consistently when non-matching value is set
                   if ( !optionSet ) {
                       elem.selectedIndex = -1;
                   }
                   return values;
               }
           }
       }
   } );
   
   // Radios and checkboxes getter/setter
   jQuery.each( [ "radio", "checkbox" ], function() {
       jQuery.valHooks[ this ] = {
           set: function( elem, value ) {
               if ( Array.isArray( value ) ) {
                   return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
               }
           }
       };
       if ( !support.checkOn ) {
           jQuery.valHooks[ this ].get = function( elem ) {
               return elem.getAttribute( "value" ) === null ? "on" : elem.value;
           };
       }
   } );
   
   
   
   
   // Return jQuery for attributes-only inclusion
   
   
   var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
   
   jQuery.extend( jQuery.event, {
   
       trigger: function( event, data, elem, onlyHandlers ) {
   
           var i, cur, tmp, bubbleType, ontype, handle, special,
               eventPath = [ elem || document ],
               type = hasOwn.call( event, "type" ) ? event.type : event,
               namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
   
           cur = tmp = elem = elem || document;
   
           // Don't do events on text and comment nodes
           if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
               return;
           }
   
           // focus/blur morphs to focusin/out; ensure we're not firing them right now
           if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
               return;
           }
   
           if ( type.indexOf( "." ) > -1 ) {
   
               // Namespaced trigger; create a regexp to match event type in handle()
               namespaces = type.split( "." );
               type = namespaces.shift();
               namespaces.sort();
           }
           ontype = type.indexOf( ":" ) < 0 && "on" + type;
   
           // Caller can pass in a jQuery.Event object, Object, or just an event type string
           event = event[ jQuery.expando ] ?
               event :
               new jQuery.Event( type, typeof event === "object" && event );
   
           // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
           event.isTrigger = onlyHandlers ? 2 : 3;
           event.namespace = namespaces.join( "." );
           event.rnamespace = event.namespace ?
               new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
               null;
   
           // Clean up the event in case it is being reused
           event.result = undefined;
           if ( !event.target ) {
               event.target = elem;
           }
   
           // Clone any incoming data and prepend the event, creating the handler arg list
           data = data == null ?
               [ event ] :
               jQuery.makeArray( data, [ event ] );
   
           // Allow special events to draw outside the lines
           special = jQuery.event.special[ type ] || {};
           if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
               return;
           }
   
           // Determine event propagation path in advance, per W3C events spec (#9951)
           // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
           if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
   
               bubbleType = special.delegateType || type;
               if ( !rfocusMorph.test( bubbleType + type ) ) {
                   cur = cur.parentNode;
               }
               for ( ; cur; cur = cur.parentNode ) {
                   eventPath.push( cur );
                   tmp = cur;
               }
   
               // Only add window if we got to document (e.g., not plain obj or detached DOM)
               if ( tmp === ( elem.ownerDocument || document ) ) {
                   eventPath.push( tmp.defaultView || tmp.parentWindow || window );
               }
           }
   
           // Fire handlers on the event path
           i = 0;
           while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
   
               event.type = i > 1 ?
                   bubbleType :
                   special.bindType || type;
   
               // jQuery handler
               handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
                   dataPriv.get( cur, "handle" );
               if ( handle ) {
                   handle.apply( cur, data );
               }
   
               // Native handler
               handle = ontype && cur[ ontype ];
               if ( handle && handle.apply && acceptData( cur ) ) {
                   event.result = handle.apply( cur, data );
                   if ( event.result === false ) {
                       event.preventDefault();
                   }
               }
           }
           event.type = type;
   
           // If nobody prevented the default action, do it now
           if ( !onlyHandlers && !event.isDefaultPrevented() ) {
   
               if ( ( !special._default ||
                   special._default.apply( eventPath.pop(), data ) === false ) &&
                   acceptData( elem ) ) {
   
                   // Call a native DOM method on the target with the same name as the event.
                   // Don't do default actions on window, that's where global variables be (#6170)
                   if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
   
                       // Don't re-trigger an onFOO event when we call its FOO() method
                       tmp = elem[ ontype ];
   
                       if ( tmp ) {
                           elem[ ontype ] = null;
                       }
   
                       // Prevent re-triggering of the same event, since we already bubbled it above
                       jQuery.event.triggered = type;
                       elem[ type ]();
                       jQuery.event.triggered = undefined;
   
                       if ( tmp ) {
                           elem[ ontype ] = tmp;
                       }
                   }
               }
           }
   
           return event.result;
       },
   
       // Piggyback on a donor event to simulate a different one
       // Used only for `focus(in | out)` events
       simulate: function( type, elem, event ) {
           var e = jQuery.extend(
               new jQuery.Event(),
               event,
               {
                   type: type,
                   isSimulated: true
               }
           );
   
           jQuery.event.trigger( e, null, elem );
       }
   
   } );
   
   jQuery.fn.extend( {
   
       trigger: function( type, data ) {
           return this.each( function() {
               jQuery.event.trigger( type, data, this );
           } );
       },
       triggerHandler: function( type, data ) {
           var elem = this[ 0 ];
           if ( elem ) {
               return jQuery.event.trigger( type, data, elem, true );
           }
       }
   } );
   
   
   jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
       "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
       "change select submit keydown keypress keyup contextmenu" ).split( " " ),
       function( i, name ) {
   
       // Handle event binding
       jQuery.fn[ name ] = function( data, fn ) {
           return arguments.length > 0 ?
               this.on( name, null, data, fn ) :
               this.trigger( name );
       };
   } );
   
   jQuery.fn.extend( {
       hover: function( fnOver, fnOut ) {
           return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
       }
   } );
   
   
   
   
   support.focusin = "onfocusin" in window;
   
   
   // Support: Firefox <=44
   // Firefox doesn't have focus(in | out) events
   // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
   //
   // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
   // focus(in | out) events fire after focus & blur events,
   // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
   // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
   if ( !support.focusin ) {
       jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
   
           // Attach a single capturing handler on the document while someone wants focusin/focusout
           var handler = function( event ) {
               jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
           };
   
           jQuery.event.special[ fix ] = {
               setup: function() {
                   var doc = this.ownerDocument || this,
                       attaches = dataPriv.access( doc, fix );
   
                   if ( !attaches ) {
                       doc.addEventListener( orig, handler, true );
                   }
                   dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
               },
               teardown: function() {
                   var doc = this.ownerDocument || this,
                       attaches = dataPriv.access( doc, fix ) - 1;
   
                   if ( !attaches ) {
                       doc.removeEventListener( orig, handler, true );
                       dataPriv.remove( doc, fix );
   
                   } else {
                       dataPriv.access( doc, fix, attaches );
                   }
               }
           };
       } );
   }
   var location = window.location;
   
   var nonce = jQuery.now();
   
   var rquery = ( /\?/ );
   
   
   
   // Cross-browser xml parsing
   jQuery.parseXML = function( data ) {
       var xml;
       if ( !data || typeof data !== "string" ) {
           return null;
       }
   
       // Support: IE 9 - 11 only
       // IE throws on parseFromString with invalid input.
       try {
           xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
       } catch ( e ) {
           xml = undefined;
       }
   
       if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
           jQuery.error( "Invalid XML: " + data );
       }
       return xml;
   };
   
   
   var
       rbracket = /\[\]$/,
       rCRLF = /\r?\n/g,
       rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
       rsubmittable = /^(?:input|select|textarea|keygen)/i;
   
   function buildParams( prefix, obj, traditional, add ) {
       var name;
   
       if ( Array.isArray( obj ) ) {
   
           // Serialize array item.
           jQuery.each( obj, function( i, v ) {
               if ( traditional || rbracket.test( prefix ) ) {
   
                   // Treat each array item as a scalar.
                   add( prefix, v );
   
               } else {
   
                   // Item is non-scalar (array or object), encode its numeric index.
                   buildParams(
                       prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
                       v,
                       traditional,
                       add
                   );
               }
           } );
   
       } else if ( !traditional && jQuery.type( obj ) === "object" ) {
   
           // Serialize object item.
           for ( name in obj ) {
               buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
           }
   
       } else {
   
           // Serialize scalar item.
           add( prefix, obj );
       }
   }
   
   // Serialize an array of form elements or a set of
   // key/values into a query string
   jQuery.param = function( a, traditional ) {
       var prefix,
           s = [],
           add = function( key, valueOrFunction ) {
   
               // If value is a function, invoke it and use its return value
               var value = jQuery.isFunction( valueOrFunction ) ?
                   valueOrFunction() :
                   valueOrFunction;
   
               s[ s.length ] = encodeURIComponent( key ) + "=" +
                   encodeURIComponent( value == null ? "" : value );
           };
   
       // If an array was passed in, assume that it is an array of form elements.
       if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
   
           // Serialize the form elements
           jQuery.each( a, function() {
               add( this.name, this.value );
           } );
   
       } else {
   
           // If traditional, encode the "old" way (the way 1.3.2 or older
           // did it), otherwise encode params recursively.
           for ( prefix in a ) {
               buildParams( prefix, a[ prefix ], traditional, add );
           }
       }
   
       // Return the resulting serialization
       return s.join( "&" );
   };
   
   jQuery.fn.extend( {
       serialize: function() {
           return jQuery.param( this.serializeArray() );
       },
       serializeArray: function() {
           return this.map( function() {
   
               // Can add propHook for "elements" to filter or add form elements
               var elements = jQuery.prop( this, "elements" );
               return elements ? jQuery.makeArray( elements ) : this;
           } )
           .filter( function() {
               var type = this.type;
   
               // Use .is( ":disabled" ) so that fieldset[disabled] works
               return this.name && !jQuery( this ).is( ":disabled" ) &&
                   rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
                   ( this.checked || !rcheckableType.test( type ) );
           } )
           .map( function( i, elem ) {
               var val = jQuery( this ).val();
   
               if ( val == null ) {
                   return null;
               }
   
               if ( Array.isArray( val ) ) {
                   return jQuery.map( val, function( val ) {
                       return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
                   } );
               }
   
               return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
           } ).get();
       }
   } );
   
   
   var
       r20 = /%20/g,
       rhash = /#.*$/,
       rantiCache = /([?&])_=[^&]*/,
       rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
   
       // #7653, #8125, #8152: local protocol detection
       rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
       rnoContent = /^(?:GET|HEAD)$/,
       rprotocol = /^\/\//,
   
       /* Prefilters
        * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
        * 2) These are called:
        *    - BEFORE asking for a transport
        *    - AFTER param serialization (s.data is a string if s.processData is true)
        * 3) key is the dataType
        * 4) the catchall symbol "*" can be used
        * 5) execution will start with transport dataType and THEN continue down to "*" if needed
        */
       prefilters = {},
   
       /* Transports bindings
        * 1) key is the dataType
        * 2) the catchall symbol "*" can be used
        * 3) selection will start with transport dataType and THEN go to "*" if needed
        */
       transports = {},
   
       // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
       allTypes = "*/".concat( "*" ),
   
       // Anchor tag for parsing the document origin
       originAnchor = document.createElement( "a" );
       originAnchor.href = location.href;
   
   // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
   function addToPrefiltersOrTransports( structure ) {
   
       // dataTypeExpression is optional and defaults to "*"
       return function( dataTypeExpression, func ) {
   
           if ( typeof dataTypeExpression !== "string" ) {
               func = dataTypeExpression;
               dataTypeExpression = "*";
           }
   
           var dataType,
               i = 0,
               dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
   
           if ( jQuery.isFunction( func ) ) {
   
               // For each dataType in the dataTypeExpression
               while ( ( dataType = dataTypes[ i++ ] ) ) {
   
                   // Prepend if requested
                   if ( dataType[ 0 ] === "+" ) {
                       dataType = dataType.slice( 1 ) || "*";
                       ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
   
                   // Otherwise append
                   } else {
                       ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
                   }
               }
           }
       };
   }
   
   // Base inspection function for prefilters and transports
   function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
   
       var inspected = {},
           seekingTransport = ( structure === transports );
   
       function inspect( dataType ) {
           var selected;
           inspected[ dataType ] = true;
           jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
               var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
               if ( typeof dataTypeOrTransport === "string" &&
                   !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
   
                   options.dataTypes.unshift( dataTypeOrTransport );
                   inspect( dataTypeOrTransport );
                   return false;
               } else if ( seekingTransport ) {
                   return !( selected = dataTypeOrTransport );
               }
           } );
           return selected;
       }
   
       return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
   }
   
   // A special extend for ajax options
   // that takes "flat" options (not to be deep extended)
   // Fixes #9887
   function ajaxExtend( target, src ) {
       var key, deep,
           flatOptions = jQuery.ajaxSettings.flatOptions || {};
   
       for ( key in src ) {
           if ( src[ key ] !== undefined ) {
               ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
           }
       }
       if ( deep ) {
           jQuery.extend( true, target, deep );
       }
   
       return target;
   }
   
   /* Handles responses to an ajax request:
    * - finds the right dataType (mediates between content-type and expected dataType)
    * - returns the corresponding response
    */
   function ajaxHandleResponses( s, jqXHR, responses ) {
   
       var ct, type, finalDataType, firstDataType,
           contents = s.contents,
           dataTypes = s.dataTypes;
   
       // Remove auto dataType and get content-type in the process
       while ( dataTypes[ 0 ] === "*" ) {
           dataTypes.shift();
           if ( ct === undefined ) {
               ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
           }
       }
   
       // Check if we're dealing with a known content-type
       if ( ct ) {
           for ( type in contents ) {
               if ( contents[ type ] && contents[ type ].test( ct ) ) {
                   dataTypes.unshift( type );
                   break;
               }
           }
       }
   
       // Check to see if we have a response for the expected dataType
       if ( dataTypes[ 0 ] in responses ) {
           finalDataType = dataTypes[ 0 ];
       } else {
   
           // Try convertible dataTypes
           for ( type in responses ) {
               if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
                   finalDataType = type;
                   break;
               }
               if ( !firstDataType ) {
                   firstDataType = type;
               }
           }
   
           // Or just use first one
           finalDataType = finalDataType || firstDataType;
       }
   
       // If we found a dataType
       // We add the dataType to the list if needed
       // and return the corresponding response
       if ( finalDataType ) {
           if ( finalDataType !== dataTypes[ 0 ] ) {
               dataTypes.unshift( finalDataType );
           }
           return responses[ finalDataType ];
       }
   }
   
   /* Chain conversions given the request and the original response
    * Also sets the responseXXX fields on the jqXHR instance
    */
   function ajaxConvert( s, response, jqXHR, isSuccess ) {
       var conv2, current, conv, tmp, prev,
           converters = {},
   
           // Work with a copy of dataTypes in case we need to modify it for conversion
           dataTypes = s.dataTypes.slice();
   
       // Create converters map with lowercased keys
       if ( dataTypes[ 1 ] ) {
           for ( conv in s.converters ) {
               converters[ conv.toLowerCase() ] = s.converters[ conv ];
           }
       }
   
       current = dataTypes.shift();
   
       // Convert to each sequential dataType
       while ( current ) {
   
           if ( s.responseFields[ current ] ) {
               jqXHR[ s.responseFields[ current ] ] = response;
           }
   
           // Apply the dataFilter if provided
           if ( !prev && isSuccess && s.dataFilter ) {
               response = s.dataFilter( response, s.dataType );
           }
   
           prev = current;
           current = dataTypes.shift();
   
           if ( current ) {
   
               // There's only work to do if current dataType is non-auto
               if ( current === "*" ) {
   
                   current = prev;
   
               // Convert response if prev dataType is non-auto and differs from current
               } else if ( prev !== "*" && prev !== current ) {
   
                   // Seek a direct converter
                   conv = converters[ prev + " " + current ] || converters[ "* " + current ];
   
                   // If none found, seek a pair
                   if ( !conv ) {
                       for ( conv2 in converters ) {
   
                           // If conv2 outputs current
                           tmp = conv2.split( " " );
                           if ( tmp[ 1 ] === current ) {
   
                               // If prev can be converted to accepted input
                               conv = converters[ prev + " " + tmp[ 0 ] ] ||
                                   converters[ "* " + tmp[ 0 ] ];
                               if ( conv ) {
   
                                   // Condense equivalence converters
                                   if ( conv === true ) {
                                       conv = converters[ conv2 ];
   
                                   // Otherwise, insert the intermediate dataType
                                   } else if ( converters[ conv2 ] !== true ) {
                                       current = tmp[ 0 ];
                                       dataTypes.unshift( tmp[ 1 ] );
                                   }
                                   break;
                               }
                           }
                       }
                   }
   
                   // Apply converter (if not an equivalence)
                   if ( conv !== true ) {
   
                       // Unless errors are allowed to bubble, catch and return them
                       if ( conv && s.throws ) {
                           response = conv( response );
                       } else {
                           try {
                               response = conv( response );
                           } catch ( e ) {
                               return {
                                   state: "parsererror",
                                   error: conv ? e : "No conversion from " + prev + " to " + current
                               };
                           }
                       }
                   }
               }
           }
       }
   
       return { state: "success", data: response };
   }
   
   jQuery.extend( {
   
       // Counter for holding the number of active queries
       active: 0,
   
       // Last-Modified header cache for next request
       lastModified: {},
       etag: {},
   
       ajaxSettings: {
           url: location.href,
           type: "GET",
           isLocal: rlocalProtocol.test( location.protocol ),
           global: true,
           processData: true,
           async: true,
           contentType: "application/x-www-form-urlencoded; charset=UTF-8",
   
           /*
           timeout: 0,
           data: null,
           dataType: null,
           username: null,
           password: null,
           cache: null,
           throws: false,
           traditional: false,
           headers: {},
           */
   
           accepts: {
               "*": allTypes,
               text: "text/plain",
               html: "text/html",
               xml: "application/xml, text/xml",
               json: "application/json, text/javascript"
           },
   
           contents: {
               xml: /\bxml\b/,
               html: /\bhtml/,
               json: /\bjson\b/
           },
   
           responseFields: {
               xml: "responseXML",
               text: "responseText",
               json: "responseJSON"
           },
   
           // Data converters
           // Keys separate source (or catchall "*") and destination types with a single space
           converters: {
   
               // Convert anything to text
               "* text": String,
   
               // Text to html (true = no transformation)
               "text html": true,
   
               // Evaluate text as a json expression
               "text json": JSON.parse,
   
               // Parse text as xml
               "text xml": jQuery.parseXML
           },
   
           // For options that shouldn't be deep extended:
           // you can add your own custom options here if
           // and when you create one that shouldn't be
           // deep extended (see ajaxExtend)
           flatOptions: {
               url: true,
               context: true
           }
       },
   
       // Creates a full fledged settings object into target
       // with both ajaxSettings and settings fields.
       // If target is omitted, writes into ajaxSettings.
       ajaxSetup: function( target, settings ) {
           return settings ?
   
               // Building a settings object
               ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
   
               // Extending ajaxSettings
               ajaxExtend( jQuery.ajaxSettings, target );
       },
   
       ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
       ajaxTransport: addToPrefiltersOrTransports( transports ),
   
       // Main method
       ajax: function( url, options ) {
   
           // If url is an object, simulate pre-1.5 signature
           if ( typeof url === "object" ) {
               options = url;
               url = undefined;
           }
   
           // Force options to be an object
           options = options || {};
   
           var transport,
   
               // URL without anti-cache param
               cacheURL,
   
               // Response headers
               responseHeadersString,
               responseHeaders,
   
               // timeout handle
               timeoutTimer,
   
               // Url cleanup var
               urlAnchor,
   
               // Request state (becomes false upon send and true upon completion)
               completed,
   
               // To know if global events are to be dispatched
               fireGlobals,
   
               // Loop variable
               i,
   
               // uncached part of the url
               uncached,
   
               // Create the final options object
               s = jQuery.ajaxSetup( {}, options ),
   
               // Callbacks context
               callbackContext = s.context || s,
   
               // Context for global events is callbackContext if it is a DOM node or jQuery collection
               globalEventContext = s.context &&
                   ( callbackContext.nodeType || callbackContext.jquery ) ?
                       jQuery( callbackContext ) :
                       jQuery.event,
   
               // Deferreds
               deferred = jQuery.Deferred(),
               completeDeferred = jQuery.Callbacks( "once memory" ),
   
               // Status-dependent callbacks
               statusCode = s.statusCode || {},
   
               // Headers (they are sent all at once)
               requestHeaders = {},
               requestHeadersNames = {},
   
               // Default abort message
               strAbort = "canceled",
   
               // Fake xhr
               jqXHR = {
                   readyState: 0,
   
                   // Builds headers hashtable if needed
                   getResponseHeader: function( key ) {
                       var match;
                       if ( completed ) {
                           if ( !responseHeaders ) {
                               responseHeaders = {};
                               while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
                                   responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
                               }
                           }
                           match = responseHeaders[ key.toLowerCase() ];
                       }
                       return match == null ? null : match;
                   },
   
                   // Raw string
                   getAllResponseHeaders: function() {
                       return completed ? responseHeadersString : null;
                   },
   
                   // Caches the header
                   setRequestHeader: function( name, value ) {
                       if ( completed == null ) {
                           name = requestHeadersNames[ name.toLowerCase() ] =
                               requestHeadersNames[ name.toLowerCase() ] || name;
                           requestHeaders[ name ] = value;
                       }
                       return this;
                   },
   
                   // Overrides response content-type header
                   overrideMimeType: function( type ) {
                       if ( completed == null ) {
                           s.mimeType = type;
                       }
                       return this;
                   },
   
                   // Status-dependent callbacks
                   statusCode: function( map ) {
                       var code;
                       if ( map ) {
                           if ( completed ) {
   
                               // Execute the appropriate callbacks
                               jqXHR.always( map[ jqXHR.status ] );
                           } else {
   
                               // Lazy-add the new callbacks in a way that preserves old ones
                               for ( code in map ) {
                                   statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
                               }
                           }
                       }
                       return this;
                   },
   
                   // Cancel the request
                   abort: function( statusText ) {
                       var finalText = statusText || strAbort;
                       if ( transport ) {
                           transport.abort( finalText );
                       }
                       done( 0, finalText );
                       return this;
                   }
               };
   
           // Attach deferreds
           deferred.promise( jqXHR );
   
           // Add protocol if not provided (prefilters might expect it)
           // Handle falsy url in the settings object (#10093: consistency with old signature)
           // We also use the url parameter if available
           s.url = ( ( url || s.url || location.href ) + "" )
               .replace( rprotocol, location.protocol + "//" );
   
           // Alias method option to type as per ticket #12004
           s.type = options.method || options.type || s.method || s.type;
   
           // Extract dataTypes list
           s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
   
           // A cross-domain request is in order when the origin doesn't match the current origin.
           if ( s.crossDomain == null ) {
               urlAnchor = document.createElement( "a" );
   
               // Support: IE <=8 - 11, Edge 12 - 13
               // IE throws exception on accessing the href property if url is malformed,
               // e.g. http://example.com:80x/
               try {
                   urlAnchor.href = s.url;
   
                   // Support: IE <=8 - 11 only
                   // Anchor's host property isn't correctly set when s.url is relative
                   urlAnchor.href = urlAnchor.href;
                   s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
                       urlAnchor.protocol + "//" + urlAnchor.host;
               } catch ( e ) {
   
                   // If there is an error parsing the URL, assume it is crossDomain,
                   // it can be rejected by the transport if it is invalid
                   s.crossDomain = true;
               }
           }
   
           // Convert data if not already a string
           if ( s.data && s.processData && typeof s.data !== "string" ) {
               s.data = jQuery.param( s.data, s.traditional );
           }
   
           // Apply prefilters
           inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
   
           // If request was aborted inside a prefilter, stop there
           if ( completed ) {
               return jqXHR;
           }
   
           // We can fire global events as of now if asked to
           // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
           fireGlobals = jQuery.event && s.global;
   
           // Watch for a new set of requests
           if ( fireGlobals && jQuery.active++ === 0 ) {
               jQuery.event.trigger( "ajaxStart" );
           }
   
           // Uppercase the type
           s.type = s.type.toUpperCase();
   
           // Determine if request has content
           s.hasContent = !rnoContent.test( s.type );
   
           // Save the URL in case we're toying with the If-Modified-Since
           // and/or If-None-Match header later on
           // Remove hash to simplify url manipulation
           cacheURL = s.url.replace( rhash, "" );
   
           // More options handling for requests with no content
           if ( !s.hasContent ) {
   
               // Remember the hash so we can put it back
               uncached = s.url.slice( cacheURL.length );
   
               // If data is available, append data to url
               if ( s.data ) {
                   cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
   
                   // #9682: remove data so that it's not used in an eventual retry
                   delete s.data;
               }
   
               // Add or update anti-cache param if needed
               if ( s.cache === false ) {
                   cacheURL = cacheURL.replace( rantiCache, "$1" );
                   uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
               }
   
               // Put hash and anti-cache on the URL that will be requested (gh-1732)
               s.url = cacheURL + uncached;
   
           // Change '%20' to '+' if this is encoded form body content (gh-2658)
           } else if ( s.data && s.processData &&
               ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
               s.data = s.data.replace( r20, "+" );
           }
   
           // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
           if ( s.ifModified ) {
               if ( jQuery.lastModified[ cacheURL ] ) {
                   jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
               }
               if ( jQuery.etag[ cacheURL ] ) {
                   jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
               }
           }
   
           // Set the correct header, if data is being sent
           if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
               jqXHR.setRequestHeader( "Content-Type", s.contentType );
           }
   
           // Set the Accepts header for the server, depending on the dataType
           jqXHR.setRequestHeader(
               "Accept",
               s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
                   s.accepts[ s.dataTypes[ 0 ] ] +
                       ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
                   s.accepts[ "*" ]
           );
   
           // Check for headers option
           for ( i in s.headers ) {
               jqXHR.setRequestHeader( i, s.headers[ i ] );
           }
   
           // Allow custom headers/mimetypes and early abort
           if ( s.beforeSend &&
               ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
   
               // Abort if not done already and return
               return jqXHR.abort();
           }
   
           // Aborting is no longer a cancellation
           strAbort = "abort";
   
           // Install callbacks on deferreds
           completeDeferred.add( s.complete );
           jqXHR.done( s.success );
           jqXHR.fail( s.error );
   
           // Get transport
           transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
   
           // If no transport, we auto-abort
           if ( !transport ) {
               done( -1, "No Transport" );
           } else {
               jqXHR.readyState = 1;
   
               // Send global event
               if ( fireGlobals ) {
                   globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
               }
   
               // If request was aborted inside ajaxSend, stop there
               if ( completed ) {
                   return jqXHR;
               }
   
               // Timeout
               if ( s.async && s.timeout > 0 ) {
                   timeoutTimer = window.setTimeout( function() {
                       jqXHR.abort( "timeout" );
                   }, s.timeout );
               }
   
               try {
                   completed = false;
                   transport.send( requestHeaders, done );
               } catch ( e ) {
   
                   // Rethrow post-completion exceptions
                   if ( completed ) {
                       throw e;
                   }
   
                   // Propagate others as results
                   done( -1, e );
               }
           }
   
           // Callback for when everything is done
           function done( status, nativeStatusText, responses, headers ) {
               var isSuccess, success, error, response, modified,
                   statusText = nativeStatusText;
   
               // Ignore repeat invocations
               if ( completed ) {
                   return;
               }
   
               completed = true;
   
               // Clear timeout if it exists
               if ( timeoutTimer ) {
                   window.clearTimeout( timeoutTimer );
               }
   
               // Dereference transport for early garbage collection
               // (no matter how long the jqXHR object will be used)
               transport = undefined;
   
               // Cache response headers
               responseHeadersString = headers || "";
   
               // Set readyState
               jqXHR.readyState = status > 0 ? 4 : 0;
   
               // Determine if successful
               isSuccess = status >= 200 && status < 300 || status === 304;
   
               // Get response data
               if ( responses ) {
                   response = ajaxHandleResponses( s, jqXHR, responses );
               }
   
               // Convert no matter what (that way responseXXX fields are always set)
               response = ajaxConvert( s, response, jqXHR, isSuccess );
   
               // If successful, handle type chaining
               if ( isSuccess ) {
   
                   // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
                   if ( s.ifModified ) {
                       modified = jqXHR.getResponseHeader( "Last-Modified" );
                       if ( modified ) {
                           jQuery.lastModified[ cacheURL ] = modified;
                       }
                       modified = jqXHR.getResponseHeader( "etag" );
                       if ( modified ) {
                           jQuery.etag[ cacheURL ] = modified;
                       }
                   }
   
                   // if no content
                   if ( status === 204 || s.type === "HEAD" ) {
                       statusText = "nocontent";
   
                   // if not modified
                   } else if ( status === 304 ) {
                       statusText = "notmodified";
   
                   // If we have data, let's convert it
                   } else {
                       statusText = response.state;
                       success = response.data;
                       error = response.error;
                       isSuccess = !error;
                   }
               } else {
   
                   // Extract error from statusText and normalize for non-aborts
                   error = statusText;
                   if ( status || !statusText ) {
                       statusText = "error";
                       if ( status < 0 ) {
                           status = 0;
                       }
                   }
               }
   
               // Set data for the fake xhr object
               jqXHR.status = status;
               jqXHR.statusText = ( nativeStatusText || statusText ) + "";
   
               // Success/Error
               if ( isSuccess ) {
                   deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
               } else {
                   deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
               }
   
               // Status-dependent callbacks
               jqXHR.statusCode( statusCode );
               statusCode = undefined;
   
               if ( fireGlobals ) {
                   globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
                       [ jqXHR, s, isSuccess ? success : error ] );
               }
   
               // Complete
               completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
   
               if ( fireGlobals ) {
                   globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
   
                   // Handle the global AJAX counter
                   if ( !( --jQuery.active ) ) {
                       jQuery.event.trigger( "ajaxStop" );
                   }
               }
           }
   
           return jqXHR;
       },
   
       getJSON: function( url, data, callback ) {
           return jQuery.get( url, data, callback, "json" );
       },
   
       getScript: function( url, callback ) {
           return jQuery.get( url, undefined, callback, "script" );
       }
   } );
   
   jQuery.each( [ "get", "post" ], function( i, method ) {
       jQuery[ method ] = function( url, data, callback, type ) {
   
           // Shift arguments if data argument was omitted
           if ( jQuery.isFunction( data ) ) {
               type = type || callback;
               callback = data;
               data = undefined;
           }
   
           // The url can be an options object (which then must have .url)
           return jQuery.ajax( jQuery.extend( {
               url: url,
               type: method,
               dataType: type,
               data: data,
               success: callback
           }, jQuery.isPlainObject( url ) && url ) );
       };
   } );
   
   
   jQuery._evalUrl = function( url ) {
       return jQuery.ajax( {
           url: url,
   
           // Make this explicit, since user can override this through ajaxSetup (#11264)
           type: "GET",
           dataType: "script",
           cache: true,
           async: false,
           global: false,
           "throws": true
       } );
   };
   
   
   jQuery.fn.extend( {
       wrapAll: function( html ) {
           var wrap;
   
           if ( this[ 0 ] ) {
               if ( jQuery.isFunction( html ) ) {
                   html = html.call( this[ 0 ] );
               }
   
               // The elements to wrap the target around
               wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
   
               if ( this[ 0 ].parentNode ) {
                   wrap.insertBefore( this[ 0 ] );
               }
   
               wrap.map( function() {
                   var elem = this;
   
                   while ( elem.firstElementChild ) {
                       elem = elem.firstElementChild;
                   }
   
                   return elem;
               } ).append( this );
           }
   
           return this;
       },
   
       wrapInner: function( html ) {
           if ( jQuery.isFunction( html ) ) {
               return this.each( function( i ) {
                   jQuery( this ).wrapInner( html.call( this, i ) );
               } );
           }
   
           return this.each( function() {
               var self = jQuery( this ),
                   contents = self.contents();
   
               if ( contents.length ) {
                   contents.wrapAll( html );
   
               } else {
                   self.append( html );
               }
           } );
       },
   
       wrap: function( html ) {
           var isFunction = jQuery.isFunction( html );
   
           return this.each( function( i ) {
               jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
           } );
       },
   
       unwrap: function( selector ) {
           this.parent( selector ).not( "body" ).each( function() {
               jQuery( this ).replaceWith( this.childNodes );
           } );
           return this;
       }
   } );
   
   
   jQuery.expr.pseudos.hidden = function( elem ) {
       return !jQuery.expr.pseudos.visible( elem );
   };
   jQuery.expr.pseudos.visible = function( elem ) {
       return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
   };
   
   
   
   
   jQuery.ajaxSettings.xhr = function() {
       try {
           return new window.XMLHttpRequest();
       } catch ( e ) {}
   };
   
   var xhrSuccessStatus = {
   
           // File protocol always yields status code 0, assume 200
           0: 200,
   
           // Support: IE <=9 only
           // #1450: sometimes IE returns 1223 when it should be 204
           1223: 204
       },
       xhrSupported = jQuery.ajaxSettings.xhr();
   
   support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
   support.ajax = xhrSupported = !!xhrSupported;
   
   jQuery.ajaxTransport( function( options ) {
       var callback, errorCallback;
   
       // Cross domain only allowed if supported through XMLHttpRequest
       if ( support.cors || xhrSupported && !options.crossDomain ) {
           return {
               send: function( headers, complete ) {
                   var i,
                       xhr = options.xhr();
   
                   xhr.open(
                       options.type,
                       options.url,
                       options.async,
                       options.username,
                       options.password
                   );
   
                   // Apply custom fields if provided
                   if ( options.xhrFields ) {
                       for ( i in options.xhrFields ) {
                           xhr[ i ] = options.xhrFields[ i ];
                       }
                   }
   
                   // Override mime type if needed
                   if ( options.mimeType && xhr.overrideMimeType ) {
                       xhr.overrideMimeType( options.mimeType );
                   }
   
                   // X-Requested-With header
                   // For cross-domain requests, seeing as conditions for a preflight are
                   // akin to a jigsaw puzzle, we simply never set it to be sure.
                   // (it can always be set on a per-request basis or even using ajaxSetup)
                   // For same-domain requests, won't change header if already provided.
                   if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
                       headers[ "X-Requested-With" ] = "XMLHttpRequest";
                   }
   
                   // Set headers
                   for ( i in headers ) {
                       xhr.setRequestHeader( i, headers[ i ] );
                   }
   
                   // Callback
                   callback = function( type ) {
                       return function() {
                           if ( callback ) {
                               callback = errorCallback = xhr.onload =
                                   xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
   
                               if ( type === "abort" ) {
                                   xhr.abort();
                               } else if ( type === "error" ) {
   
                                   // Support: IE <=9 only
                                   // On a manual native abort, IE9 throws
                                   // errors on any property access that is not readyState
                                   if ( typeof xhr.status !== "number" ) {
                                       complete( 0, "error" );
                                   } else {
                                       complete(
   
                                           // File: protocol always yields status 0; see #8605, #14207
                                           xhr.status,
                                           xhr.statusText
                                       );
                                   }
                               } else {
                                   complete(
                                       xhrSuccessStatus[ xhr.status ] || xhr.status,
                                       xhr.statusText,
   
                                       // Support: IE <=9 only
                                       // IE9 has no XHR2 but throws on binary (trac-11426)
                                       // For XHR2 non-text, let the caller handle it (gh-2498)
                                       ( xhr.responseType || "text" ) !== "text"  ||
                                       typeof xhr.responseText !== "string" ?
                                           { binary: xhr.response } :
                                           { text: xhr.responseText },
                                       xhr.getAllResponseHeaders()
                                   );
                               }
                           }
                       };
                   };
   
                   // Listen to events
                   xhr.onload = callback();
                   errorCallback = xhr.onerror = callback( "error" );
   
                   // Support: IE 9 only
                   // Use onreadystatechange to replace onabort
                   // to handle uncaught aborts
                   if ( xhr.onabort !== undefined ) {
                       xhr.onabort = errorCallback;
                   } else {
                       xhr.onreadystatechange = function() {
   
                           // Check readyState before timeout as it changes
                           if ( xhr.readyState === 4 ) {
   
                               // Allow onerror to be called first,
                               // but that will not handle a native abort
                               // Also, save errorCallback to a variable
                               // as xhr.onerror cannot be accessed
                               window.setTimeout( function() {
                                   if ( callback ) {
                                       errorCallback();
                                   }
                               } );
                           }
                       };
                   }
   
                   // Create the abort callback
                   callback = callback( "abort" );
   
                   try {
   
                       // Do send the request (this may raise an exception)
                       xhr.send( options.hasContent && options.data || null );
                   } catch ( e ) {
   
                       // #14683: Only rethrow if this hasn't been notified as an error yet
                       if ( callback ) {
                           throw e;
                       }
                   }
               },
   
               abort: function() {
                   if ( callback ) {
                       callback();
                   }
               }
           };
       }
   } );
   
   
   
   
   // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
   jQuery.ajaxPrefilter( function( s ) {
       if ( s.crossDomain ) {
           s.contents.script = false;
       }
   } );
   
   // Install script dataType
   jQuery.ajaxSetup( {
       accepts: {
           script: "text/javascript, application/javascript, " +
               "application/ecmascript, application/x-ecmascript"
       },
       contents: {
           script: /\b(?:java|ecma)script\b/
       },
       converters: {
           "text script": function( text ) {
               jQuery.globalEval( text );
               return text;
           }
       }
   } );
   
   // Handle cache's special case and crossDomain
   jQuery.ajaxPrefilter( "script", function( s ) {
       if ( s.cache === undefined ) {
           s.cache = false;
       }
       if ( s.crossDomain ) {
           s.type = "GET";
       }
   } );
   
   // Bind script tag hack transport
   jQuery.ajaxTransport( "script", function( s ) {
   
       // This transport only deals with cross domain requests
       if ( s.crossDomain ) {
           var script, callback;
           return {
               send: function( _, complete ) {
                   script = jQuery( "<script>" ).prop( {
                       charset: s.scriptCharset,
                       src: s.url
                   } ).on(
                       "load error",
                       callback = function( evt ) {
                           script.remove();
                           callback = null;
                           if ( evt ) {
                               complete( evt.type === "error" ? 404 : 200, evt.type );
                           }
                       }
                   );
   
                   // Use native DOM manipulation to avoid our domManip AJAX trickery
                   document.head.appendChild( script[ 0 ] );
               },
               abort: function() {
                   if ( callback ) {
                       callback();
                   }
               }
           };
       }
   } );
   
   
   
   
   var oldCallbacks = [],
       rjsonp = /(=)\?(?=&|$)|\?\?/;
   
   // Default jsonp settings
   jQuery.ajaxSetup( {
       jsonp: "callback",
       jsonpCallback: function() {
           var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
           this[ callback ] = true;
           return callback;
       }
   } );
   
   // Detect, normalize options and install callbacks for jsonp requests
   jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
   
       var callbackName, overwritten, responseContainer,
           jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
               "url" :
               typeof s.data === "string" &&
                   ( s.contentType || "" )
                       .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
                   rjsonp.test( s.data ) && "data"
           );
   
       // Handle iff the expected data type is "jsonp" or we have a parameter to set
       if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
   
           // Get callback name, remembering preexisting value associated with it
           callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
               s.jsonpCallback() :
               s.jsonpCallback;
   
           // Insert callback into url or form data
           if ( jsonProp ) {
               s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
           } else if ( s.jsonp !== false ) {
               s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
           }
   
           // Use data converter to retrieve json after script execution
           s.converters[ "script json" ] = function() {
               if ( !responseContainer ) {
                   jQuery.error( callbackName + " was not called" );
               }
               return responseContainer[ 0 ];
           };
   
           // Force json dataType
           s.dataTypes[ 0 ] = "json";
   
           // Install callback
           overwritten = window[ callbackName ];
           window[ callbackName ] = function() {
               responseContainer = arguments;
           };
   
           // Clean-up function (fires after converters)
           jqXHR.always( function() {
   
               // If previous value didn't exist - remove it
               if ( overwritten === undefined ) {
                   jQuery( window ).removeProp( callbackName );
   
               // Otherwise restore preexisting value
               } else {
                   window[ callbackName ] = overwritten;
               }
   
               // Save back as free
               if ( s[ callbackName ] ) {
   
                   // Make sure that re-using the options doesn't screw things around
                   s.jsonpCallback = originalSettings.jsonpCallback;
   
                   // Save the callback name for future use
                   oldCallbacks.push( callbackName );
               }
   
               // Call if it was a function and we have a response
               if ( responseContainer && jQuery.isFunction( overwritten ) ) {
                   overwritten( responseContainer[ 0 ] );
               }
   
               responseContainer = overwritten = undefined;
           } );
   
           // Delegate to script
           return "script";
       }
   } );
   
   
   
   
   // Support: Safari 8 only
   // In Safari 8 documents created via document.implementation.createHTMLDocument
   // collapse sibling forms: the second one becomes a child of the first one.
   // Because of that, this security measure has to be disabled in Safari 8.
   // https://bugs.webkit.org/show_bug.cgi?id=137337
   support.createHTMLDocument = ( function() {
       var body = document.implementation.createHTMLDocument( "" ).body;
       body.innerHTML = "<form></form><form></form>";
       return body.childNodes.length === 2;
   } )();
   
   
   // Argument "data" should be string of html
   // context (optional): If specified, the fragment will be created in this context,
   // defaults to document
   // keepScripts (optional): If true, will include scripts passed in the html string
   jQuery.parseHTML = function( data, context, keepScripts ) {
       if ( typeof data !== "string" ) {
           return [];
       }
       if ( typeof context === "boolean" ) {
           keepScripts = context;
           context = false;
       }
   
       var base, parsed, scripts;
   
       if ( !context ) {
   
           // Stop scripts or inline event handlers from being executed immediately
           // by using document.implementation
           if ( support.createHTMLDocument ) {
               context = document.implementation.createHTMLDocument( "" );
   
               // Set the base href for the created document
               // so any parsed elements with URLs
               // are based on the document's URL (gh-2965)
               base = context.createElement( "base" );
               base.href = document.location.href;
               context.head.appendChild( base );
           } else {
               context = document;
           }
       }
   
       parsed = rsingleTag.exec( data );
       scripts = !keepScripts && [];
   
       // Single tag
       if ( parsed ) {
           return [ context.createElement( parsed[ 1 ] ) ];
       }
   
       parsed = buildFragment( [ data ], context, scripts );
   
       if ( scripts && scripts.length ) {
           jQuery( scripts ).remove();
       }
   
       return jQuery.merge( [], parsed.childNodes );
   };
   
   
   /**
    * Load a url into a page
    */
   jQuery.fn.load = function( url, params, callback ) {
       var selector, type, response,
           self = this,
           off = url.indexOf( " " );
   
       if ( off > -1 ) {
           selector = stripAndCollapse( url.slice( off ) );
           url = url.slice( 0, off );
       }
   
       // If it's a function
       if ( jQuery.isFunction( params ) ) {
   
           // We assume that it's the callback
           callback = params;
           params = undefined;
   
       // Otherwise, build a param string
       } else if ( params && typeof params === "object" ) {
           type = "POST";
       }
   
       // If we have elements to modify, make the request
       if ( self.length > 0 ) {
           jQuery.ajax( {
               url: url,
   
               // If "type" variable is undefined, then "GET" method will be used.
               // Make value of this field explicit since
               // user can override it through ajaxSetup method
               type: type || "GET",
               dataType: "html",
               data: params
           } ).done( function( responseText ) {
   
               // Save response for use in complete callback
               response = arguments;
   
               self.html( selector ?
   
                   // If a selector was specified, locate the right elements in a dummy div
                   // Exclude scripts to avoid IE 'Permission Denied' errors
                   jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
   
                   // Otherwise use the full result
                   responseText );
   
           // If the request succeeds, this function gets "data", "status", "jqXHR"
           // but they are ignored because response was set above.
           // If it fails, this function gets "jqXHR", "status", "error"
           } ).always( callback && function( jqXHR, status ) {
               self.each( function() {
                   callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
               } );
           } );
       }
   
       return this;
   };
   
   
   
   
   // Attach a bunch of functions for handling common AJAX events
   jQuery.each( [
       "ajaxStart",
       "ajaxStop",
       "ajaxComplete",
       "ajaxError",
       "ajaxSuccess",
       "ajaxSend"
   ], function( i, type ) {
       jQuery.fn[ type ] = function( fn ) {
           return this.on( type, fn );
       };
   } );
   
   
   
   
   jQuery.expr.pseudos.animated = function( elem ) {
       return jQuery.grep( jQuery.timers, function( fn ) {
           return elem === fn.elem;
       } ).length;
   };
   
   
   
   
   jQuery.offset = {
       setOffset: function( elem, options, i ) {
           var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
               position = jQuery.css( elem, "position" ),
               curElem = jQuery( elem ),
               props = {};
   
           // Set position first, in-case top/left are set even on static elem
           if ( position === "static" ) {
               elem.style.position = "relative";
           }
   
           curOffset = curElem.offset();
           curCSSTop = jQuery.css( elem, "top" );
           curCSSLeft = jQuery.css( elem, "left" );
           calculatePosition = ( position === "absolute" || position === "fixed" ) &&
               ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
   
           // Need to be able to calculate position if either
           // top or left is auto and position is either absolute or fixed
           if ( calculatePosition ) {
               curPosition = curElem.position();
               curTop = curPosition.top;
               curLeft = curPosition.left;
   
           } else {
               curTop = parseFloat( curCSSTop ) || 0;
               curLeft = parseFloat( curCSSLeft ) || 0;
           }
   
           if ( jQuery.isFunction( options ) ) {
   
               // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
               options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
           }
   
           if ( options.top != null ) {
               props.top = ( options.top - curOffset.top ) + curTop;
           }
           if ( options.left != null ) {
               props.left = ( options.left - curOffset.left ) + curLeft;
           }
   
           if ( "using" in options ) {
               options.using.call( elem, props );
   
           } else {
               curElem.css( props );
           }
       }
   };
   
   jQuery.fn.extend( {
       offset: function( options ) {
   
           // Preserve chaining for setter
           if ( arguments.length ) {
               return options === undefined ?
                   this :
                   this.each( function( i ) {
                       jQuery.offset.setOffset( this, options, i );
                   } );
           }
   
           var doc, docElem, rect, win,
               elem = this[ 0 ];
   
           if ( !elem ) {
               return;
           }
   
           // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
           // Support: IE <=11 only
           // Running getBoundingClientRect on a
           // disconnected node in IE throws an error
           if ( !elem.getClientRects().length ) {
               return { top: 0, left: 0 };
           }
   
           rect = elem.getBoundingClientRect();
   
           doc = elem.ownerDocument;
           docElem = doc.documentElement;
           win = doc.defaultView;
   
           return {
               top: rect.top + win.pageYOffset - docElem.clientTop,
               left: rect.left + win.pageXOffset - docElem.clientLeft
           };
       },
   
       position: function() {
           if ( !this[ 0 ] ) {
               return;
           }
   
           var offsetParent, offset,
               elem = this[ 0 ],
               parentOffset = { top: 0, left: 0 };
   
           // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
           // because it is its only offset parent
           if ( jQuery.css( elem, "position" ) === "fixed" ) {
   
               // Assume getBoundingClientRect is there when computed position is fixed
               offset = elem.getBoundingClientRect();
   
           } else {
   
               // Get *real* offsetParent
               offsetParent = this.offsetParent();
   
               // Get correct offsets
               offset = this.offset();
               if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
                   parentOffset = offsetParent.offset();
               }
   
               // Add offsetParent borders
               parentOffset = {
                   top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
                   left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
               };
           }
   
           // Subtract parent offsets and element margins
           return {
               top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
               left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
           };
       },
   
       // This method will return documentElement in the following cases:
       // 1) For the element inside the iframe without offsetParent, this method will return
       //    documentElement of the parent window
       // 2) For the hidden or detached element
       // 3) For body or html element, i.e. in case of the html node - it will return itself
       //
       // but those exceptions were never presented as a real life use-cases
       // and might be considered as more preferable results.
       //
       // This logic, however, is not guaranteed and can change at any point in the future
       offsetParent: function() {
           return this.map( function() {
               var offsetParent = this.offsetParent;
   
               while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
                   offsetParent = offsetParent.offsetParent;
               }
   
               return offsetParent || documentElement;
           } );
       }
   } );
   
   // Create scrollLeft and scrollTop methods
   jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
       var top = "pageYOffset" === prop;
   
       jQuery.fn[ method ] = function( val ) {
           return access( this, function( elem, method, val ) {
   
               // Coalesce documents and windows
               var win;
               if ( jQuery.isWindow( elem ) ) {
                   win = elem;
               } else if ( elem.nodeType === 9 ) {
                   win = elem.defaultView;
               }
   
               if ( val === undefined ) {
                   return win ? win[ prop ] : elem[ method ];
               }
   
               if ( win ) {
                   win.scrollTo(
                       !top ? val : win.pageXOffset,
                       top ? val : win.pageYOffset
                   );
   
               } else {
                   elem[ method ] = val;
               }
           }, method, val, arguments.length );
       };
   } );
   
   // Support: Safari <=7 - 9.1, Chrome <=37 - 49
   // Add the top/left cssHooks using jQuery.fn.position
   // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
   // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
   // getComputedStyle returns percent when specified for top/left/bottom/right;
   // rather than make the css module depend on the offset module, just check for it here
   jQuery.each( [ "top", "left" ], function( i, prop ) {
       jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
           function( elem, computed ) {
               if ( computed ) {
                   computed = curCSS( elem, prop );
   
                   // If curCSS returns percentage, fallback to offset
                   return rnumnonpx.test( computed ) ?
                       jQuery( elem ).position()[ prop ] + "px" :
                       computed;
               }
           }
       );
   } );
   
   
   // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
   jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
       jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
           function( defaultExtra, funcName ) {
   
           // Margin is only for outerHeight, outerWidth
           jQuery.fn[ funcName ] = function( margin, value ) {
               var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
                   extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
   
               return access( this, function( elem, type, value ) {
                   var doc;
   
                   if ( jQuery.isWindow( elem ) ) {
   
                       // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
                       return funcName.indexOf( "outer" ) === 0 ?
                           elem[ "inner" + name ] :
                           elem.document.documentElement[ "client" + name ];
                   }
   
                   // Get document width or height
                   if ( elem.nodeType === 9 ) {
                       doc = elem.documentElement;
   
                       // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
                       // whichever is greatest
                       return Math.max(
                           elem.body[ "scroll" + name ], doc[ "scroll" + name ],
                           elem.body[ "offset" + name ], doc[ "offset" + name ],
                           doc[ "client" + name ]
                       );
                   }
   
                   return value === undefined ?
   
                       // Get width or height on the element, requesting but not forcing parseFloat
                       jQuery.css( elem, type, extra ) :
   
                       // Set width or height on the element
                       jQuery.style( elem, type, value, extra );
               }, type, chainable ? margin : undefined, chainable );
           };
       } );
   } );
   
   
   jQuery.fn.extend( {
   
       bind: function( types, data, fn ) {
           return this.on( types, null, data, fn );
       },
       unbind: function( types, fn ) {
           return this.off( types, null, fn );
       },
   
       delegate: function( selector, types, data, fn ) {
           return this.on( types, selector, data, fn );
       },
       undelegate: function( selector, types, fn ) {
   
           // ( namespace ) or ( selector, types [, fn] )
           return arguments.length === 1 ?
               this.off( selector, "**" ) :
               this.off( types, selector || "**", fn );
       }
   } );
   
   jQuery.holdReady = function( hold ) {
       if ( hold ) {
           jQuery.readyWait++;
       } else {
           jQuery.ready( true );
       }
   };
   jQuery.isArray = Array.isArray;
   jQuery.parseJSON = JSON.parse;
   jQuery.nodeName = nodeName;
   
   
   
   
   // Register as a named AMD module, since jQuery can be concatenated with other
   // files that may use define, but not via a proper concatenation script that
   // understands anonymous AMD modules. A named AMD is safest and most robust
   // way to register. Lowercase jquery is used because AMD module names are
   // derived from file names, and jQuery is normally delivered in a lowercase
   // file name. Do this after creating the global so that if an AMD module wants
   // to call noConflict to hide this version of jQuery, it will work.
   
   // Note that for maximum portability, libraries that are not jQuery should
   // declare themselves as anonymous modules, and avoid setting a global if an
   // AMD loader is present. jQuery is a special case. For more information, see
   // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
   
   if ( true ) {
       !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
           return jQuery;
       }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
                   __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
   }
   
   
   
   
   var
   
       // Map over jQuery in case of overwrite
       _jQuery = window.jQuery,
   
       // Map over the $ in case of overwrite
       _$ = window.$;
   
   jQuery.noConflict = function( deep ) {
       if ( window.$ === jQuery ) {
           window.$ = _$;
       }
   
       if ( deep && window.jQuery === jQuery ) {
           window.jQuery = _jQuery;
       }
   
       return jQuery;
   };
   
   // Expose jQuery and $ identifiers, even in AMD
   // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
   // and CommonJS for browser emulators (#13566)
   if ( !noGlobal ) {
       window.jQuery = window.$ = jQuery;
   }
   
   
   
   
   return jQuery;
   } );
   
   
   /***/ }),
   /* 1 */,
   /* 2 */,
   /* 3 */,
   /* 4 */,
   /* 5 */
   /***/ (function(module, exports, __webpack_require__) {
   
   "use strict";
   
   
   __webpack_require__(6);
   
   jQuery(document).ready(function ($) {
   
     //   var myOptions = {
     //     // you can declare a default color here,
     //     // or in the data-default-color attribute on the input
     //     defaultColor: 'ddd',
     //     // a callback to fire whenever the color changes to a valid color
     //     change: function(event, ui){},
     //     // a callback to fire when the input is emptied or an invalid color
     //     clear: function() {},
     //     // hide the color picker controls on load
     //     hide: true,
     //     // show a group of common colors beneath the square
     //     // or, supply an array of colors to customize further
     //     palettes: true
     // };
     $('.color-wp').wpColorPicker();
     // $('.color-wp').wpColorPicker(myOptions);
   
   
     // let s1_options = {
     //   defaultColor: 'ddd',
     //   hide: true,
     //   palettes: true
     // }
     // $('.color-wp-s1').wpColorPicker(s1_options);
   
   });
   
   $(document).ready(function () {
     $('select').material_select();
     $('.collapsible').collapsible();
   
     var position = document.querySelectorAll('.position');
   
     var default_display = function default_display() {
   
       var val = $('.select').find(":selected").val();
   
       var position1 = document.querySelector('.position-1');
       var position2 = document.querySelector('.position-2');
       var position3 = document.querySelector('.position-3');
       var position4 = document.querySelector('.position-4');
   
       if (val == '1') {
         position1.classList.add('display-block');
       } else if (val == '2') {
         position2.classList.add('display-block');
       } else if (val == '3') {
         position3.classList.add('display-block');
       } else if (val == '4') {
         position4.classList.add('display-block');
       }
     };
   
     default_display();
   
     //  incase displya-block is added remove it ..
     var remove = function remove() {
       position.forEach(function (e) {
         e.classList.remove('display-block');
       });
     };
   
     $(".select").on("change", function (e) {
       var x = e.target;
       var val = e.target.value;
   
       var position1 = document.querySelector('.position-1');
       var position2 = document.querySelector('.position-2');
       var position3 = document.querySelector('.position-3');
       var position4 = document.querySelector('.position-4');
   
       if (val == '1') {
         remove();
         position1.classList.add('display-block');
       } else if (val == '2') {
         remove();
         position2.classList.add('display-block');
       } else if (val == '3') {
         remove();
         position3.classList.add('display-block');
       } else if (val == '4') {
         remove();
         position4.classList.add('display-block');
       }
     });
   
     // can impove this code -  
     // https://stackoverflow.com/a/32631357/2591092
     // https://stackoverflow.com/questions/11208021/jquery-add-css-class-depending-on-selectbox-option
   });
   
   /***/ }),
   /* 6 */
   /***/ (function(module, exports, __webpack_require__) {
   
   var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
    * Materialize v0.100.1 (http://materializecss.com)
    * Copyright 2014-2017 Materialize
    * MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE)
    */
   var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
   
   function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
   
   // Check for jQuery.
   if (typeof jQuery === 'undefined') {
     var jQuery;
     // Check if require is a defined function.
     if (true) {
       jQuery = $ = __webpack_require__(0);
       // Else use the dollar sign alias.
     } else {
       jQuery = $;
     }
   }
   ; /*
     * jQuery Easing v1.4.0 - http://gsgd.co.uk/sandbox/jquery/easing/
     * Open source under the BSD License.
     * Copyright © 2008 George McGinley Smith
     * All rights reserved.
     * https://raw.github.com/gdsmith/jquery-easing/master/LICENSE
     */
   
   (function (factory) {
     if (true) {
       !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0)], __WEBPACK_AMD_DEFINE_RESULT__ = function ($) {
         return factory($);
       }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
                   __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
     } else if (typeof module === "object" && typeof module.exports === "object") {
       exports = factory(require('jquery'));
     } else {
       factory(jQuery);
     }
   })(function ($) {
   
     // Preserve the original jQuery "swing" easing as "jswing"
     $.easing['jswing'] = $.easing['swing'];
   
     var pow = Math.pow,
         sqrt = Math.sqrt,
         sin = Math.sin,
         cos = Math.cos,
         PI = Math.PI,
         c1 = 1.70158,
         c2 = c1 * 1.525,
         c3 = c1 + 1,
         c4 = 2 * PI / 3,
         c5 = 2 * PI / 4.5;
   
     // x is the fraction of animation progress, in the range 0..1
     function bounceOut(x) {
       var n1 = 7.5625,
           d1 = 2.75;
       if (x < 1 / d1) {
         return n1 * x * x;
       } else if (x < 2 / d1) {
         return n1 * (x -= 1.5 / d1) * x + .75;
       } else if (x < 2.5 / d1) {
         return n1 * (x -= 2.25 / d1) * x + .9375;
       } else {
         return n1 * (x -= 2.625 / d1) * x + .984375;
       }
     }
   
     $.extend($.easing, {
       def: 'easeOutQuad',
       swing: function (x) {
         return $.easing[$.easing.def](x);
       },
       easeInQuad: function (x) {
         return x * x;
       },
       easeOutQuad: function (x) {
         return 1 - (1 - x) * (1 - x);
       },
       easeInOutQuad: function (x) {
         return x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2;
       },
       easeInCubic: function (x) {
         return x * x * x;
       },
       easeOutCubic: function (x) {
         return 1 - pow(1 - x, 3);
       },
       easeInOutCubic: function (x) {
         return x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2;
       },
       easeInQuart: function (x) {
         return x * x * x * x;
       },
       easeOutQuart: function (x) {
         return 1 - pow(1 - x, 4);
       },
       easeInOutQuart: function (x) {
         return x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2;
       },
       easeInQuint: function (x) {
         return x * x * x * x * x;
       },
       easeOutQuint: function (x) {
         return 1 - pow(1 - x, 5);
       },
       easeInOutQuint: function (x) {
         return x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2;
       },
       easeInSine: function (x) {
         return 1 - cos(x * PI / 2);
       },
       easeOutSine: function (x) {
         return sin(x * PI / 2);
       },
       easeInOutSine: function (x) {
         return -(cos(PI * x) - 1) / 2;
       },
       easeInExpo: function (x) {
         return x === 0 ? 0 : pow(2, 10 * x - 10);
       },
       easeOutExpo: function (x) {
         return x === 1 ? 1 : 1 - pow(2, -10 * x);
       },
       easeInOutExpo: function (x) {
         return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? pow(2, 20 * x - 10) / 2 : (2 - pow(2, -20 * x + 10)) / 2;
       },
       easeInCirc: function (x) {
         return 1 - sqrt(1 - pow(x, 2));
       },
       easeOutCirc: function (x) {
         return sqrt(1 - pow(x - 1, 2));
       },
       easeInOutCirc: function (x) {
         return x < 0.5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2;
       },
       easeInElastic: function (x) {
         return x === 0 ? 0 : x === 1 ? 1 : -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * c4);
       },
       easeOutElastic: function (x) {
         return x === 0 ? 0 : x === 1 ? 1 : pow(2, -10 * x) * sin((x * 10 - 0.75) * c4) + 1;
       },
       easeInOutElastic: function (x) {
         return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c5)) / 2 : pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c5) / 2 + 1;
       },
       easeInBack: function (x) {
         return c3 * x * x * x - c1 * x * x;
       },
       easeOutBack: function (x) {
         return 1 + c3 * pow(x - 1, 3) + c1 * pow(x - 1, 2);
       },
       easeInOutBack: function (x) {
         return x < 0.5 ? pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2) / 2 : (pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;
       },
       easeInBounce: function (x) {
         return 1 - bounceOut(1 - x);
       },
       easeOutBounce: bounceOut,
       easeInOutBounce: function (x) {
         return x < 0.5 ? (1 - bounceOut(1 - 2 * x)) / 2 : (1 + bounceOut(2 * x - 1)) / 2;
       }
     });
   });; // Custom Easing
   jQuery.extend(jQuery.easing, {
     easeInOutMaterial: function (x, t, b, c, d) {
       if ((t /= d / 2) < 1) return c / 2 * t * t + b;
       return c / 4 * ((t -= 2) * t * t + 2) + b;
     }
   });; /*! VelocityJS.org (1.2.3). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */
   /*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
   /*! Note that this has been modified by Materialize to confirm that Velocity is not already being imported. */
   jQuery.Velocity ? console.log("Velocity is already loaded. You may be needlessly importing Velocity again; note that Materialize includes Velocity.") : (!function (e) {
     function t(e) {
       var t = e.length,
           a = r.type(e);return "function" === a || r.isWindow(e) ? !1 : 1 === e.nodeType && t ? !0 : "array" === a || 0 === t || "number" == typeof t && t > 0 && t - 1 in e;
     }if (!e.jQuery) {
       var r = function (e, t) {
         return new r.fn.init(e, t);
       };r.isWindow = function (e) {
         return null != e && e == e.window;
       }, r.type = function (e) {
         return null == e ? e + "" : "object" == typeof e || "function" == typeof e ? n[i.call(e)] || "object" : typeof e;
       }, r.isArray = Array.isArray || function (e) {
         return "array" === r.type(e);
       }, r.isPlainObject = function (e) {
         var t;if (!e || "object" !== r.type(e) || e.nodeType || r.isWindow(e)) return !1;try {
           if (e.constructor && !o.call(e, "constructor") && !o.call(e.constructor.prototype, "isPrototypeOf")) return !1;
         } catch (a) {
           return !1;
         }for (t in e) {}return void 0 === t || o.call(e, t);
       }, r.each = function (e, r, a) {
         var n,
             o = 0,
             i = e.length,
             s = t(e);if (a) {
           if (s) for (; i > o && (n = r.apply(e[o], a), n !== !1); o++) {} else for (o in e) {
             if (n = r.apply(e[o], a), n === !1) break;
           }
         } else if (s) for (; i > o && (n = r.call(e[o], o, e[o]), n !== !1); o++) {} else for (o in e) {
           if (n = r.call(e[o], o, e[o]), n === !1) break;
         }return e;
       }, r.data = function (e, t, n) {
         if (void 0 === n) {
           var o = e[r.expando],
               i = o && a[o];if (void 0 === t) return i;if (i && t in i) return i[t];
         } else if (void 0 !== t) {
           var o = e[r.expando] || (e[r.expando] = ++r.uuid);return a[o] = a[o] || {}, a[o][t] = n, n;
         }
       }, r.removeData = function (e, t) {
         var n = e[r.expando],
             o = n && a[n];o && r.each(t, function (e, t) {
           delete o[t];
         });
       }, r.extend = function () {
         var e,
             t,
             a,
             n,
             o,
             i,
             s = arguments[0] || {},
             l = 1,
             u = arguments.length,
             c = !1;for ("boolean" == typeof s && (c = s, s = arguments[l] || {}, l++), "object" != typeof s && "function" !== r.type(s) && (s = {}), l === u && (s = this, l--); u > l; l++) {
           if (null != (o = arguments[l])) for (n in o) {
             e = s[n], a = o[n], s !== a && (c && a && (r.isPlainObject(a) || (t = r.isArray(a))) ? (t ? (t = !1, i = e && r.isArray(e) ? e : []) : i = e && r.isPlainObject(e) ? e : {}, s[n] = r.extend(c, i, a)) : void 0 !== a && (s[n] = a));
           }
         }return s;
       }, r.queue = function (e, a, n) {
         function o(e, r) {
           var a = r || [];return null != e && (t(Object(e)) ? !function (e, t) {
             for (var r = +t.length, a = 0, n = e.length; r > a;) {
               e[n++] = t[a++];
             }if (r !== r) for (; void 0 !== t[a];) {
               e[n++] = t[a++];
             }return e.length = n, e;
           }(a, "string" == typeof e ? [e] : e) : [].push.call(a, e)), a;
         }if (e) {
           a = (a || "fx") + "queue";var i = r.data(e, a);return n ? (!i || r.isArray(n) ? i = r.data(e, a, o(n)) : i.push(n), i) : i || [];
         }
       }, r.dequeue = function (e, t) {
         r.each(e.nodeType ? [e] : e, function (e, a) {
           t = t || "fx";var n = r.queue(a, t),
               o = n.shift();"inprogress" === o && (o = n.shift()), o && ("fx" === t && n.unshift("inprogress"), o.call(a, function () {
             r.dequeue(a, t);
           }));
         });
       }, r.fn = r.prototype = { init: function (e) {
           if (e.nodeType) return this[0] = e, this;throw new Error("Not a DOM node.");
         }, offset: function () {
           var t = this[0].getBoundingClientRect ? this[0].getBoundingClientRect() : { top: 0, left: 0 };return { top: t.top + (e.pageYOffset || document.scrollTop || 0) - (document.clientTop || 0), left: t.left + (e.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || 0) };
         }, position: function () {
           function e() {
             for (var e = this.offsetParent || document; e && "html" === !e.nodeType.toLowerCase && "static" === e.style.position;) {
               e = e.offsetParent;
             }return e || document;
           }var t = this[0],
               e = e.apply(t),
               a = this.offset(),
               n = /^(?:body|html)$/i.test(e.nodeName) ? { top: 0, left: 0 } : r(e).offset();return a.top -= parseFloat(t.style.marginTop) || 0, a.left -= parseFloat(t.style.marginLeft) || 0, e.style && (n.top += parseFloat(e.style.borderTopWidth) || 0, n.left += parseFloat(e.style.borderLeftWidth) || 0), { top: a.top - n.top, left: a.left - n.left };
         } };var a = {};r.expando = "velocity" + new Date().getTime(), r.uuid = 0;for (var n = {}, o = n.hasOwnProperty, i = n.toString, s = "Boolean Number String Function Array Date RegExp Object Error".split(" "), l = 0; l < s.length; l++) {
         n["[object " + s[l] + "]"] = s[l].toLowerCase();
       }r.fn.init.prototype = r.fn, e.Velocity = { Utilities: r };
     }
   }(window), function (e) {
     "object" == typeof module && "object" == typeof module.exports ? module.exports = e() :  true ? !(__WEBPACK_AMD_DEFINE_FACTORY__ = (e),
                   __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
                   (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
                   __WEBPACK_AMD_DEFINE_FACTORY__),
                   __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : e();
   }(function () {
     return function (e, t, r, a) {
       function n(e) {
         for (var t = -1, r = e ? e.length : 0, a = []; ++t < r;) {
           var n = e[t];n && a.push(n);
         }return a;
       }function o(e) {
         return m.isWrapped(e) ? e = [].slice.call(e) : m.isNode(e) && (e = [e]), e;
       }function i(e) {
         var t = f.data(e, "velocity");return null === t ? a : t;
       }function s(e) {
         return function (t) {
           return Math.round(t * e) * (1 / e);
         };
       }function l(e, r, a, n) {
         function o(e, t) {
           return 1 - 3 * t + 3 * e;
         }function i(e, t) {
           return 3 * t - 6 * e;
         }function s(e) {
           return 3 * e;
         }function l(e, t, r) {
           return ((o(t, r) * e + i(t, r)) * e + s(t)) * e;
         }function u(e, t, r) {
           return 3 * o(t, r) * e * e + 2 * i(t, r) * e + s(t);
         }function c(t, r) {
           for (var n = 0; m > n; ++n) {
             var o = u(r, e, a);if (0 === o) return r;var i = l(r, e, a) - t;r -= i / o;
           }return r;
         }function p() {
           for (var t = 0; b > t; ++t) {
             w[t] = l(t * x, e, a);
           }
         }function f(t, r, n) {
           var o,
               i,
               s = 0;do {
             i = r + (n - r) / 2, o = l(i, e, a) - t, o > 0 ? n = i : r = i;
           } while (Math.abs(o) > h && ++s < v);return i;
         }function d(t) {
           for (var r = 0, n = 1, o = b - 1; n != o && w[n] <= t; ++n) {
             r += x;
           }--n;var i = (t - w[n]) / (w[n + 1] - w[n]),
               s = r + i * x,
               l = u(s, e, a);return l >= y ? c(t, s) : 0 == l ? s : f(t, r, r + x);
         }function g() {
           V = !0, (e != r || a != n) && p();
         }var m = 4,
             y = .001,
             h = 1e-7,
             v = 10,
             b = 11,
             x = 1 / (b - 1),
             S = "Float32Array" in t;if (4 !== arguments.length) return !1;for (var P = 0; 4 > P; ++P) {
           if ("number" != typeof arguments[P] || isNaN(arguments[P]) || !isFinite(arguments[P])) return !1;
         }e = Math.min(e, 1), a = Math.min(a, 1), e = Math.max(e, 0), a = Math.max(a, 0);var w = S ? new Float32Array(b) : new Array(b),
             V = !1,
             C = function (t) {
           return V || g(), e === r && a === n ? t : 0 === t ? 0 : 1 === t ? 1 : l(d(t), r, n);
         };C.getControlPoints = function () {
           return [{ x: e, y: r }, { x: a, y: n }];
         };var T = "generateBezier(" + [e, r, a, n] + ")";return C.toString = function () {
           return T;
         }, C;
       }function u(e, t) {
         var r = e;return m.isString(e) ? b.Easings[e] || (r = !1) : r = m.isArray(e) && 1 === e.length ? s.apply(null, e) : m.isArray(e) && 2 === e.length ? x.apply(null, e.concat([t])) : m.isArray(e) && 4 === e.length ? l.apply(null, e) : !1, r === !1 && (r = b.Easings[b.defaults.easing] ? b.defaults.easing : v), r;
       }function c(e) {
         if (e) {
           var t = new Date().getTime(),
               r = b.State.calls.length;r > 1e4 && (b.State.calls = n(b.State.calls));for (var o = 0; r > o; o++) {
             if (b.State.calls[o]) {
               var s = b.State.calls[o],
                   l = s[0],
                   u = s[2],
                   d = s[3],
                   g = !!d,
                   y = null;d || (d = b.State.calls[o][3] = t - 16);for (var h = Math.min((t - d) / u.duration, 1), v = 0, x = l.length; x > v; v++) {
                 var P = l[v],
                     V = P.element;if (i(V)) {
                   var C = !1;if (u.display !== a && null !== u.display && "none" !== u.display) {
                     if ("flex" === u.display) {
                       var T = ["-webkit-box", "-moz-box", "-ms-flexbox", "-webkit-flex"];f.each(T, function (e, t) {
                         S.setPropertyValue(V, "display", t);
                       });
                     }S.setPropertyValue(V, "display", u.display);
                   }u.visibility !== a && "hidden" !== u.visibility && S.setPropertyValue(V, "visibility", u.visibility);for (var k in P) {
                     if ("element" !== k) {
                       var A,
                           F = P[k],
                           j = m.isString(F.easing) ? b.Easings[F.easing] : F.easing;if (1 === h) A = F.endValue;else {
                         var E = F.endValue - F.startValue;if (A = F.startValue + E * j(h, u, E), !g && A === F.currentValue) continue;
                       }if (F.currentValue = A, "tween" === k) y = A;else {
                         if (S.Hooks.registered[k]) {
                           var H = S.Hooks.getRoot(k),
                               N = i(V).rootPropertyValueCache[H];N && (F.rootPropertyValue = N);
                         }var L = S.setPropertyValue(V, k, F.currentValue + (0 === parseFloat(A) ? "" : F.unitType), F.rootPropertyValue, F.scrollData);S.Hooks.registered[k] && (i(V).rootPropertyValueCache[H] = S.Normalizations.registered[H] ? S.Normalizations.registered[H]("extract", null, L[1]) : L[1]), "transform" === L[0] && (C = !0);
                       }
                     }
                   }u.mobileHA && i(V).transformCache.translate3d === a && (i(V).transformCache.translate3d = "(0px, 0px, 0px)", C = !0), C && S.flushTransformCache(V);
                 }
               }u.display !== a && "none" !== u.display && (b.State.calls[o][2].display = !1), u.visibility !== a && "hidden" !== u.visibility && (b.State.calls[o][2].visibility = !1), u.progress && u.progress.call(s[1], s[1], h, Math.max(0, d + u.duration - t), d, y), 1 === h && p(o);
             }
           }
         }b.State.isTicking && w(c);
       }function p(e, t) {
         if (!b.State.calls[e]) return !1;for (var r = b.State.calls[e][0], n = b.State.calls[e][1], o = b.State.calls[e][2], s = b.State.calls[e][4], l = !1, u = 0, c = r.length; c > u; u++) {
           var p = r[u].element;if (t || o.loop || ("none" === o.display && S.setPropertyValue(p, "display", o.display), "hidden" === o.visibility && S.setPropertyValue(p, "visibility", o.visibility)), o.loop !== !0 && (f.queue(p)[1] === a || !/\.velocityQueueEntryFlag/i.test(f.queue(p)[1])) && i(p)) {
             i(p).isAnimating = !1, i(p).rootPropertyValueCache = {};var d = !1;f.each(S.Lists.transforms3D, function (e, t) {
               var r = /^scale/.test(t) ? 1 : 0,
                   n = i(p).transformCache[t];i(p).transformCache[t] !== a && new RegExp("^\\(" + r + "[^.]").test(n) && (d = !0, delete i(p).transformCache[t]);
             }), o.mobileHA && (d = !0, delete i(p).transformCache.translate3d), d && S.flushTransformCache(p), S.Values.removeClass(p, "velocity-animating");
           }if (!t && o.complete && !o.loop && u === c - 1) try {
             o.complete.call(n, n);
           } catch (g) {
             setTimeout(function () {
               throw g;
             }, 1);
           }s && o.loop !== !0 && s(n), i(p) && o.loop === !0 && !t && (f.each(i(p).tweensContainer, function (e, t) {
             /^rotate/.test(e) && 360 === parseFloat(t.endValue) && (t.endValue = 0, t.startValue = 360), /^backgroundPosition/.test(e) && 100 === parseFloat(t.endValue) && "%" === t.unitType && (t.endValue = 0, t.startValue = 100);
           }), b(p, "reverse", { loop: !0, delay: o.delay })), o.queue !== !1 && f.dequeue(p, o.queue);
         }b.State.calls[e] = !1;for (var m = 0, y = b.State.calls.length; y > m; m++) {
           if (b.State.calls[m] !== !1) {
             l = !0;break;
           }
         }l === !1 && (b.State.isTicking = !1, delete b.State.calls, b.State.calls = []);
       }var f,
           d = function () {
         if (r.documentMode) return r.documentMode;for (var e = 7; e > 4; e--) {
           var t = r.createElement("div");if (t.innerHTML = "<!--[if IE " + e + "]><span></span><![endif]-->", t.getElementsByTagName("span").length) return t = null, e;
         }return a;
       }(),
           g = function () {
         var e = 0;return t.webkitRequestAnimationFrame || t.mozRequestAnimationFrame || function (t) {
           var r,
               a = new Date().getTime();return r = Math.max(0, 16 - (a - e)), e = a + r, setTimeout(function () {
             t(a + r);
           }, r);
         };
       }(),
           m = { isString: function (e) {
           return "string" == typeof e;
         }, isArray: Array.isArray || function (e) {
           return "[object Array]" === Object.prototype.toString.call(e);
         }, isFunction: function (e) {
           return "[object Function]" === Object.prototype.toString.call(e);
         }, isNode: function (e) {
           return e && e.nodeType;
         }, isNodeList: function (e) {
           return "object" == typeof e && /^\[object (HTMLCollection|NodeList|Object)\]$/.test(Object.prototype.toString.call(e)) && e.length !== a && (0 === e.length || "object" == typeof e[0] && e[0].nodeType > 0);
         }, isWrapped: function (e) {
           return e && (e.jquery || t.Zepto && t.Zepto.zepto.isZ(e));
         }, isSVG: function (e) {
           return t.SVGElement && e instanceof t.SVGElement;
         }, isEmptyObject: function (e) {
           for (var t in e) {
             return !1;
           }return !0;
         } },
           y = !1;if (e.fn && e.fn.jquery ? (f = e, y = !0) : f = t.Velocity.Utilities, 8 >= d && !y) throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");if (7 >= d) return void (jQuery.fn.velocity = jQuery.fn.animate);var h = 400,
           v = "swing",
           b = { State: { isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent), isAndroid: /Android/i.test(navigator.userAgent), isGingerbread: /Android 2\.3\.[3-7]/i.test(navigator.userAgent), isChrome: t.chrome, isFirefox: /Firefox/i.test(navigator.userAgent), prefixElement: r.createElement("div"), prefixMatches: {}, scrollAnchor: null, scrollPropertyLeft: null, scrollPropertyTop: null, isTicking: !1, calls: [] }, CSS: {}, Utilities: f, Redirects: {}, Easings: {}, Promise: t.Promise, defaults: { queue: "", duration: h, easing: v, begin: a, complete: a, progress: a, display: a, visibility: a, loop: !1, delay: !1, mobileHA: !0, _cacheValues: !0 }, init: function (e) {
           f.data(e, "velocity", { isSVG: m.isSVG(e), isAnimating: !1, computedStyle: null, tweensContainer: null, rootPropertyValueCache: {}, transformCache: {} });
         }, hook: null, mock: !1, version: { major: 1, minor: 2, patch: 2 }, debug: !1 };t.pageYOffset !== a ? (b.State.scrollAnchor = t, b.State.scrollPropertyLeft = "pageXOffset", b.State.scrollPropertyTop = "pageYOffset") : (b.State.scrollAnchor = r.documentElement || r.body.parentNode || r.body, b.State.scrollPropertyLeft = "scrollLeft", b.State.scrollPropertyTop = "scrollTop");var x = function () {
         function e(e) {
           return -e.tension * e.x - e.friction * e.v;
         }function t(t, r, a) {
           var n = { x: t.x + a.dx * r, v: t.v + a.dv * r, tension: t.tension, friction: t.friction };return { dx: n.v, dv: e(n) };
         }function r(r, a) {
           var n = { dx: r.v, dv: e(r) },
               o = t(r, .5 * a, n),
               i = t(r, .5 * a, o),
               s = t(r, a, i),
               l = 1 / 6 * (n.dx + 2 * (o.dx + i.dx) + s.dx),
               u = 1 / 6 * (n.dv + 2 * (o.dv + i.dv) + s.dv);return r.x = r.x + l * a, r.v = r.v + u * a, r;
         }return function a(e, t, n) {
           var o,
               i,
               s,
               l = { x: -1, v: 0, tension: null, friction: null },
               u = [0],
               c = 0,
               p = 1e-4,
               f = .016;for (e = parseFloat(e) || 500, t = parseFloat(t) || 20, n = n || null, l.tension = e, l.friction = t, o = null !== n, o ? (c = a(e, t), i = c / n * f) : i = f; s = r(s || l, i), u.push(1 + s.x), c += 16, Math.abs(s.x) > p && Math.abs(s.v) > p;) {}return o ? function (e) {
             return u[e * (u.length - 1) | 0];
           } : c;
         };
       }();b.Easings = { linear: function (e) {
           return e;
         }, swing: function (e) {
           return .5 - Math.cos(e * Math.PI) / 2;
         }, spring: function (e) {
           return 1 - Math.cos(4.5 * e * Math.PI) * Math.exp(6 * -e);
         } }, f.each([["ease", [.25, .1, .25, 1]], ["ease-in", [.42, 0, 1, 1]], ["ease-out", [0, 0, .58, 1]], ["ease-in-out", [.42, 0, .58, 1]], ["easeInSine", [.47, 0, .745, .715]], ["easeOutSine", [.39, .575, .565, 1]], ["easeInOutSine", [.445, .05, .55, .95]], ["easeInQuad", [.55, .085, .68, .53]], ["easeOutQuad", [.25, .46, .45, .94]], ["easeInOutQuad", [.455, .03, .515, .955]], ["easeInCubic", [.55, .055, .675, .19]], ["easeOutCubic", [.215, .61, .355, 1]], ["easeInOutCubic", [.645, .045, .355, 1]], ["easeInQuart", [.895, .03, .685, .22]], ["easeOutQuart", [.165, .84, .44, 1]], ["easeInOutQuart", [.77, 0, .175, 1]], ["easeInQuint", [.755, .05, .855, .06]], ["easeOutQuint", [.23, 1, .32, 1]], ["easeInOutQuint", [.86, 0, .07, 1]], ["easeInExpo", [.95, .05, .795, .035]], ["easeOutExpo", [.19, 1, .22, 1]], ["easeInOutExpo", [1, 0, 0, 1]], ["easeInCirc", [.6, .04, .98, .335]], ["easeOutCirc", [.075, .82, .165, 1]], ["easeInOutCirc", [.785, .135, .15, .86]]], function (e, t) {
         b.Easings[t[0]] = l.apply(null, t[1]);
       });var S = b.CSS = { RegEx: { isHex: /^#([A-f\d]{3}){1,2}$/i, valueUnwrap: /^[A-z]+\((.*)\)$/i, wrappedValueAlreadyExtracted: /[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/, valueSplit: /([A-z]+\(.+\))|(([A-z0-9#-.]+?)(?=\s|$))/gi }, Lists: { colors: ["fill", "stroke", "stopColor", "color", "backgroundColor", "borderColor", "borderTopColor", "borderRightColor", "borderBottomColor", "borderLeftColor", "outlineColor"], transformsBase: ["translateX", "translateY", "scale", "scaleX", "scaleY", "skewX", "skewY", "rotateZ"], transforms3D: ["transformPerspective", "translateZ", "scaleZ", "rotateX", "rotateY"] }, Hooks: { templates: { textShadow: ["Color X Y Blur", "black 0px 0px 0px"], boxShadow: ["Color X Y Blur Spread", "black 0px 0px 0px 0px"], clip: ["Top Right Bottom Left", "0px 0px 0px 0px"], backgroundPosition: ["X Y", "0% 0%"], transformOrigin: ["X Y Z", "50% 50% 0px"], perspectiveOrigin: ["X Y", "50% 50%"] }, registered: {}, register: function () {
             for (var e = 0; e < S.Lists.colors.length; e++) {
               var t = "color" === S.Lists.colors[e] ? "0 0 0 1" : "255 255 255 1";S.Hooks.templates[S.Lists.colors[e]] = ["Red Green Blue Alpha", t];
             }var r, a, n;if (d) for (r in S.Hooks.templates) {
               a = S.Hooks.templates[r], n = a[0].split(" ");var o = a[1].match(S.RegEx.valueSplit);"Color" === n[0] && (n.push(n.shift()), o.push(o.shift()), S.Hooks.templates[r] = [n.join(" "), o.join(" ")]);
             }for (r in S.Hooks.templates) {
               a = S.Hooks.templates[r], n = a[0].split(" ");for (var e in n) {
                 var i = r + n[e],
                     s = e;S.Hooks.registered[i] = [r, s];
               }
             }
           }, getRoot: function (e) {
             var t = S.Hooks.registered[e];return t ? t[0] : e;
           }, cleanRootPropertyValue: function (e, t) {
             return S.RegEx.valueUnwrap.test(t) && (t = t.match(S.RegEx.valueUnwrap)[1]), S.Values.isCSSNullValue(t) && (t = S.Hooks.templates[e][1]), t;
           }, extractValue: function (e, t) {
             var r = S.Hooks.registered[e];if (r) {
               var a = r[0],
                   n = r[1];return t = S.Hooks.cleanRootPropertyValue(a, t), t.toString().match(S.RegEx.valueSplit)[n];
             }return t;
           }, injectValue: function (e, t, r) {
             var a = S.Hooks.registered[e];if (a) {
               var n,
                   o,
                   i = a[0],
                   s = a[1];return r = S.Hooks.cleanRootPropertyValue(i, r), n = r.toString().match(S.RegEx.valueSplit), n[s] = t, o = n.join(" ");
             }return r;
           } }, Normalizations: { registered: { clip: function (e, t, r) {
               switch (e) {case "name":
                   return "clip";case "extract":
                   var a;return S.RegEx.wrappedValueAlreadyExtracted.test(r) ? a = r : (a = r.toString().match(S.RegEx.valueUnwrap), a = a ? a[1].replace(/,(\s+)?/g, " ") : r), a;case "inject":
                   return "rect(" + r + ")";}
             }, blur: function (e, t, r) {
               switch (e) {case "name":
                   return b.State.isFirefox ? "filter" : "-webkit-filter";case "extract":
                   var a = parseFloat(r);if (!a && 0 !== a) {
                     var n = r.toString().match(/blur\(([0-9]+[A-z]+)\)/i);a = n ? n[1] : 0;
                   }return a;case "inject":
                   return parseFloat(r) ? "blur(" + r + ")" : "none";}
             }, opacity: function (e, t, r) {
               if (8 >= d) switch (e) {case "name":
                   return "filter";case "extract":
                   var a = r.toString().match(/alpha\(opacity=(.*)\)/i);return r = a ? a[1] / 100 : 1;case "inject":
                   return t.style.zoom = 1, parseFloat(r) >= 1 ? "" : "alpha(opacity=" + parseInt(100 * parseFloat(r), 10) + ")";} else switch (e) {case "name":
                   return "opacity";case "extract":
                   return r;case "inject":
                   return r;}
             } }, register: function () {
             9 >= d || b.State.isGingerbread || (S.Lists.transformsBase = S.Lists.transformsBase.concat(S.Lists.transforms3D));for (var e = 0; e < S.Lists.transformsBase.length; e++) {
               !function () {
                 var t = S.Lists.transformsBase[e];S.Normalizations.registered[t] = function (e, r, n) {
                   switch (e) {case "name":
                       return "transform";case "extract":
                       return i(r) === a || i(r).transformCache[t] === a ? /^scale/i.test(t) ? 1 : 0 : i(r).transformCache[t].replace(/[()]/g, "");case "inject":
                       var o = !1;switch (t.substr(0, t.length - 1)) {case "translate":
                           o = !/(%|px|em|rem|vw|vh|\d)$/i.test(n);break;case "scal":case "scale":
                           b.State.isAndroid && i(r).transformCache[t] === a && 1 > n && (n = 1), o = !/(\d)$/i.test(n);break;case "skew":
                           o = !/(deg|\d)$/i.test(n);break;case "rotate":
                           o = !/(deg|\d)$/i.test(n);}return o || (i(r).transformCache[t] = "(" + n + ")"), i(r).transformCache[t];}
                 };
               }();
             }for (var e = 0; e < S.Lists.colors.length; e++) {
               !function () {
                 var t = S.Lists.colors[e];S.Normalizations.registered[t] = function (e, r, n) {
                   switch (e) {case "name":
                       return t;case "extract":
                       var o;if (S.RegEx.wrappedValueAlreadyExtracted.test(n)) o = n;else {
                         var i,
                             s = { black: "rgb(0, 0, 0)", blue: "rgb(0, 0, 255)", gray: "rgb(128, 128, 128)", green: "rgb(0, 128, 0)", red: "rgb(255, 0, 0)", white: "rgb(255, 255, 255)" };/^[A-z]+$/i.test(n) ? i = s[n] !== a ? s[n] : s.black : S.RegEx.isHex.test(n) ? i = "rgb(" + S.Values.hexToRgb(n).join(" ") + ")" : /^rgba?\(/i.test(n) || (i = s.black), o = (i || n).toString().match(S.RegEx.valueUnwrap)[1].replace(/,(\s+)?/g, " ");
                       }return 8 >= d || 3 !== o.split(" ").length || (o += " 1"), o;case "inject":
                       return 8 >= d ? 4 === n.split(" ").length && (n = n.split(/\s+/).slice(0, 3).join(" ")) : 3 === n.split(" ").length && (n += " 1"), (8 >= d ? "rgb" : "rgba") + "(" + n.replace(/\s+/g, ",").replace(/\.(\d)+(?=,)/g, "") + ")";}
                 };
               }();
             }
           } }, Names: { camelCase: function (e) {
             return e.replace(/-(\w)/g, function (e, t) {
               return t.toUpperCase();
             });
           }, SVGAttribute: function (e) {
             var t = "width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";return (d || b.State.isAndroid && !b.State.isChrome) && (t += "|transform"), new RegExp("^(" + t + ")$", "i").test(e);
           }, prefixCheck: function (e) {
             if (b.State.prefixMatches[e]) return [b.State.prefixMatches[e], !0];for (var t = ["", "Webkit", "Moz", "ms", "O"], r = 0, a = t.length; a > r; r++) {
               var n;if (n = 0 === r ? e : t[r] + e.replace(/^\w/, function (e) {
                 return e.toUpperCase();
               }), m.isString(b.State.prefixElement.style[n])) return b.State.prefixMatches[e] = n, [n, !0];
             }return [e, !1];
           } }, Values: { hexToRgb: function (e) {
             var t,
                 r = /^#?([a-f\d])([a-f\d])([a-f\d])$/i,
                 a = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;return e = e.replace(r, function (e, t, r, a) {
               return t + t + r + r + a + a;
             }), t = a.exec(e), t ? [parseInt(t[1], 16), parseInt(t[2], 16), parseInt(t[3], 16)] : [0, 0, 0];
           }, isCSSNullValue: function (e) {
             return 0 == e || /^(none|auto|transparent|(rgba\(0, ?0, ?0, ?0\)))$/i.test(e);
           }, getUnitType: function (e) {
             return (/^(rotate|skew)/i.test(e) ? "deg" : /(^(scale|scaleX|scaleY|scaleZ|alpha|flexGrow|flexHeight|zIndex|fontWeight)$)|((opacity|red|green|blue|alpha)$)/i.test(e) ? "" : "px"
             );
           }, getDisplayType: function (e) {
             var t = e && e.tagName.toString().toLowerCase();return (/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(t) ? "inline" : /^(li)$/i.test(t) ? "list-item" : /^(tr)$/i.test(t) ? "table-row" : /^(table)$/i.test(t) ? "table" : /^(tbody)$/i.test(t) ? "table-row-group" : "block"
             );
           }, addClass: function (e, t) {
             e.classList ? e.classList.add(t) : e.className += (e.className.length ? " " : "") + t;
           }, removeClass: function (e, t) {
             e.classList ? e.classList.remove(t) : e.className = e.className.toString().replace(new RegExp("(^|\\s)" + t.split(" ").join("|") + "(\\s|$)", "gi"), " ");
           } }, getPropertyValue: function (e, r, n, o) {
           function s(e, r) {
             function n() {
               u && S.setPropertyValue(e, "display", "none");
             }var l = 0;if (8 >= d) l = f.css(e, r);else {
               var u = !1;if (/^(width|height)$/.test(r) && 0 === S.getPropertyValue(e, "display") && (u = !0, S.setPropertyValue(e, "display", S.Values.getDisplayType(e))), !o) {
                 if ("height" === r && "border-box" !== S.getPropertyValue(e, "boxSizing").toString().toLowerCase()) {
                   var c = e.offsetHeight - (parseFloat(S.getPropertyValue(e, "borderTopWidth")) || 0) - (parseFloat(S.getPropertyValue(e, "borderBottomWidth")) || 0) - (parseFloat(S.getPropertyValue(e, "paddingTop")) || 0) - (parseFloat(S.getPropertyValue(e, "paddingBottom")) || 0);return n(), c;
                 }if ("width" === r && "border-box" !== S.getPropertyValue(e, "boxSizing").toString().toLowerCase()) {
                   var p = e.offsetWidth - (parseFloat(S.getPropertyValue(e, "borderLeftWidth")) || 0) - (parseFloat(S.getPropertyValue(e, "borderRightWidth")) || 0) - (parseFloat(S.getPropertyValue(e, "paddingLeft")) || 0) - (parseFloat(S.getPropertyValue(e, "paddingRight")) || 0);return n(), p;
                 }
               }var g;g = i(e) === a ? t.getComputedStyle(e, null) : i(e).computedStyle ? i(e).computedStyle : i(e).computedStyle = t.getComputedStyle(e, null), "borderColor" === r && (r = "borderTopColor"), l = 9 === d && "filter" === r ? g.getPropertyValue(r) : g[r], ("" === l || null === l) && (l = e.style[r]), n();
             }if ("auto" === l && /^(top|right|bottom|left)$/i.test(r)) {
               var m = s(e, "position");("fixed" === m || "absolute" === m && /top|left/i.test(r)) && (l = f(e).position()[r] + "px");
             }return l;
           }var l;if (S.Hooks.registered[r]) {
             var u = r,
                 c = S.Hooks.getRoot(u);n === a && (n = S.getPropertyValue(e, S.Names.prefixCheck(c)[0])), S.Normalizations.registered[c] && (n = S.Normalizations.registered[c]("extract", e, n)), l = S.Hooks.extractValue(u, n);
           } else if (S.Normalizations.registered[r]) {
             var p, g;p = S.Normalizations.registered[r]("name", e), "transform" !== p && (g = s(e, S.Names.prefixCheck(p)[0]), S.Values.isCSSNullValue(g) && S.Hooks.templates[r] && (g = S.Hooks.templates[r][1])), l = S.Normalizations.registered[r]("extract", e, g);
           }if (!/^[\d-]/.test(l)) if (i(e) && i(e).isSVG && S.Names.SVGAttribute(r)) {
             if (/^(height|width)$/i.test(r)) try {
               l = e.getBBox()[r];
             } catch (m) {
               l = 0;
             } else l = e.getAttribute(r);
           } else l = s(e, S.Names.prefixCheck(r)[0]);return S.Values.isCSSNullValue(l) && (l = 0), b.debug >= 2 && console.log("Get " + r + ": " + l), l;
         }, setPropertyValue: function (e, r, a, n, o) {
           var s = r;if ("scroll" === r) o.container ? o.container["scroll" + o.direction] = a : "Left" === o.direction ? t.scrollTo(a, o.alternateValue) : t.scrollTo(o.alternateValue, a);else if (S.Normalizations.registered[r] && "transform" === S.Normalizations.registered[r]("name", e)) S.Normalizations.registered[r]("inject", e, a), s = "transform", a = i(e).transformCache[r];else {
             if (S.Hooks.registered[r]) {
               var l = r,
                   u = S.Hooks.getRoot(r);n = n || S.getPropertyValue(e, u), a = S.Hooks.injectValue(l, a, n), r = u;
             }if (S.Normalizations.registered[r] && (a = S.Normalizations.registered[r]("inject", e, a), r = S.Normalizations.registered[r]("name", e)), s = S.Names.prefixCheck(r)[0], 8 >= d) try {
               e.style[s] = a;
             } catch (c) {
               b.debug && console.log("Browser does not support [" + a + "] for [" + s + "]");
             } else i(e) && i(e).isSVG && S.Names.SVGAttribute(r) ? e.setAttribute(r, a) : e.style[s] = a;b.debug >= 2 && console.log("Set " + r + " (" + s + "): " + a);
           }return [s, a];
         }, flushTransformCache: function (e) {
           function t(t) {
             return parseFloat(S.getPropertyValue(e, t));
           }var r = "";if ((d || b.State.isAndroid && !b.State.isChrome) && i(e).isSVG) {
             var a = { translate: [t("translateX"), t("translateY")], skewX: [t("skewX")], skewY: [t("skewY")], scale: 1 !== t("scale") ? [t("scale"), t("scale")] : [t("scaleX"), t("scaleY")], rotate: [t("rotateZ"), 0, 0] };f.each(i(e).transformCache, function (e) {
               /^translate/i.test(e) ? e = "translate" : /^scale/i.test(e) ? e = "scale" : /^rotate/i.test(e) && (e = "rotate"), a[e] && (r += e + "(" + a[e].join(" ") + ") ", delete a[e]);
             });
           } else {
             var n, o;f.each(i(e).transformCache, function (t) {
               return n = i(e).transformCache[t], "transformPerspective" === t ? (o = n, !0) : (9 === d && "rotateZ" === t && (t = "rotate"), void (r += t + n + " "));
             }), o && (r = "perspective" + o + " " + r);
           }S.setPropertyValue(e, "transform", r);
         } };S.Hooks.register(), S.Normalizations.register(), b.hook = function (e, t, r) {
         var n = a;return e = o(e), f.each(e, function (e, o) {
           if (i(o) === a && b.init(o), r === a) n === a && (n = b.CSS.getPropertyValue(o, t));else {
             var s = b.CSS.setPropertyValue(o, t, r);"transform" === s[0] && b.CSS.flushTransformCache(o), n = s;
           }
         }), n;
       };var P = function () {
         function e() {
           return s ? k.promise || null : l;
         }function n() {
           function e(e) {
             function p(e, t) {
               var r = a,
                   n = a,
                   i = a;return m.isArray(e) ? (r = e[0], !m.isArray(e[1]) && /^[\d-]/.test(e[1]) || m.isFunction(e[1]) || S.RegEx.isHex.test(e[1]) ? i = e[1] : (m.isString(e[1]) && !S.RegEx.isHex.test(e[1]) || m.isArray(e[1])) && (n = t ? e[1] : u(e[1], s.duration), e[2] !== a && (i = e[2]))) : r = e, t || (n = n || s.easing), m.isFunction(r) && (r = r.call(o, V, w)), m.isFunction(i) && (i = i.call(o, V, w)), [r || 0, n, i];
             }function d(e, t) {
               var r, a;return a = (t || "0").toString().toLowerCase().replace(/[%A-z]+$/, function (e) {
                 return r = e, "";
               }), r || (r = S.Values.getUnitType(e)), [a, r];
             }function h() {
               var e = { myParent: o.parentNode || r.body, position: S.getPropertyValue(o, "position"), fontSize: S.getPropertyValue(o, "fontSize") },
                   a = e.position === L.lastPosition && e.myParent === L.lastParent,
                   n = e.fontSize === L.lastFontSize;L.lastParent = e.myParent, L.lastPosition = e.position, L.lastFontSize = e.fontSize;var s = 100,
                   l = {};if (n && a) l.emToPx = L.lastEmToPx, l.percentToPxWidth = L.lastPercentToPxWidth, l.percentToPxHeight = L.lastPercentToPxHeight;else {
                 var u = i(o).isSVG ? r.createElementNS("http://www.w3.org/2000/svg", "rect") : r.createElement("div");b.init(u), e.myParent.appendChild(u), f.each(["overflow", "overflowX", "overflowY"], function (e, t) {
                   b.CSS.setPropertyValue(u, t, "hidden");
                 }), b.CSS.setPropertyValue(u, "position", e.position), b.CSS.setPropertyValue(u, "fontSize", e.fontSize), b.CSS.setPropertyValue(u, "boxSizing", "content-box"), f.each(["minWidth", "maxWidth", "width", "minHeight", "maxHeight", "height"], function (e, t) {
                   b.CSS.setPropertyValue(u, t, s + "%");
                 }), b.CSS.setPropertyValue(u, "paddingLeft", s + "em"), l.percentToPxWidth = L.lastPercentToPxWidth = (parseFloat(S.getPropertyValue(u, "width", null, !0)) || 1) / s, l.percentToPxHeight = L.lastPercentToPxHeight = (parseFloat(S.getPropertyValue(u, "height", null, !0)) || 1) / s, l.emToPx = L.lastEmToPx = (parseFloat(S.getPropertyValue(u, "paddingLeft")) || 1) / s, e.myParent.removeChild(u);
               }return null === L.remToPx && (L.remToPx = parseFloat(S.getPropertyValue(r.body, "fontSize")) || 16), null === L.vwToPx && (L.vwToPx = parseFloat(t.innerWidth) / 100, L.vhToPx = parseFloat(t.innerHeight) / 100), l.remToPx = L.remToPx, l.vwToPx = L.vwToPx, l.vhToPx = L.vhToPx, b.debug >= 1 && console.log("Unit ratios: " + JSON.stringify(l), o), l;
             }if (s.begin && 0 === V) try {
               s.begin.call(g, g);
             } catch (x) {
               setTimeout(function () {
                 throw x;
               }, 1);
             }if ("scroll" === A) {
               var P,
                   C,
                   T,
                   F = /^x$/i.test(s.axis) ? "Left" : "Top",
                   j = parseFloat(s.offset) || 0;s.container ? m.isWrapped(s.container) || m.isNode(s.container) ? (s.container = s.container[0] || s.container, P = s.container["scroll" + F], T = P + f(o).position()[F.toLowerCase()] + j) : s.container = null : (P = b.State.scrollAnchor[b.State["scrollProperty" + F]], C = b.State.scrollAnchor[b.State["scrollProperty" + ("Left" === F ? "Top" : "Left")]], T = f(o).offset()[F.toLowerCase()] + j), l = { scroll: { rootPropertyValue: !1, startValue: P, currentValue: P, endValue: T, unitType: "", easing: s.easing, scrollData: { container: s.container, direction: F, alternateValue: C } }, element: o }, b.debug && console.log("tweensContainer (scroll): ", l.scroll, o);
             } else if ("reverse" === A) {
               if (!i(o).tweensContainer) return void f.dequeue(o, s.queue);"none" === i(o).opts.display && (i(o).opts.display = "auto"), "hidden" === i(o).opts.visibility && (i(o).opts.visibility = "visible"), i(o).opts.loop = !1, i(o).opts.begin = null, i(o).opts.complete = null, v.easing || delete s.easing, v.duration || delete s.duration, s = f.extend({}, i(o).opts, s);var E = f.extend(!0, {}, i(o).tweensContainer);for (var H in E) {
                 if ("element" !== H) {
                   var N = E[H].startValue;E[H].startValue = E[H].currentValue = E[H].endValue, E[H].endValue = N, m.isEmptyObject(v) || (E[H].easing = s.easing), b.debug && console.log("reverse tweensContainer (" + H + "): " + JSON.stringify(E[H]), o);
                 }
               }l = E;
             } else if ("start" === A) {
               var E;i(o).tweensContainer && i(o).isAnimating === !0 && (E = i(o).tweensContainer), f.each(y, function (e, t) {
                 if (RegExp("^" + S.Lists.colors.join("$|^") + "$").test(e)) {
                   var r = p(t, !0),
                       n = r[0],
                       o = r[1],
                       i = r[2];if (S.RegEx.isHex.test(n)) {
                     for (var s = ["Red", "Green", "Blue"], l = S.Values.hexToRgb(n), u = i ? S.Values.hexToRgb(i) : a, c = 0; c < s.length; c++) {
                       var f = [l[c]];o && f.push(o), u !== a && f.push(u[c]), y[e + s[c]] = f;
                     }delete y[e];
                   }
                 }
               });for (var z in y) {
                 var O = p(y[z]),
                     q = O[0],
                     $ = O[1],
                     M = O[2];z = S.Names.camelCase(z);var I = S.Hooks.getRoot(z),
                     B = !1;if (i(o).isSVG || "tween" === I || S.Names.prefixCheck(I)[1] !== !1 || S.Normalizations.registered[I] !== a) {
                   (s.display !== a && null !== s.display && "none" !== s.display || s.visibility !== a && "hidden" !== s.visibility) && /opacity|filter/.test(z) && !M && 0 !== q && (M = 0), s._cacheValues && E && E[z] ? (M === a && (M = E[z].endValue + E[z].unitType), B = i(o).rootPropertyValueCache[I]) : S.Hooks.registered[z] ? M === a ? (B = S.getPropertyValue(o, I), M = S.getPropertyValue(o, z, B)) : B = S.Hooks.templates[I][1] : M === a && (M = S.getPropertyValue(o, z));var W,
                       G,
                       Y,
                       D = !1;if (W = d(z, M), M = W[0], Y = W[1], W = d(z, q), q = W[0].replace(/^([+-\/*])=/, function (e, t) {
                     return D = t, "";
                   }), G = W[1], M = parseFloat(M) || 0, q = parseFloat(q) || 0, "%" === G && (/^(fontSize|lineHeight)$/.test(z) ? (q /= 100, G = "em") : /^scale/.test(z) ? (q /= 100, G = "") : /(Red|Green|Blue)$/i.test(z) && (q = q / 100 * 255, G = "")), /[\/*]/.test(D)) G = Y;else if (Y !== G && 0 !== M) if (0 === q) G = Y;else {
                     n = n || h();var Q = /margin|padding|left|right|width|text|word|letter/i.test(z) || /X$/.test(z) || "x" === z ? "x" : "y";switch (Y) {case "%":
                         M *= "x" === Q ? n.percentToPxWidth : n.percentToPxHeight;break;case "px":
                         break;default:
                         M *= n[Y + "ToPx"];}switch (G) {case "%":
                         M *= 1 / ("x" === Q ? n.percentToPxWidth : n.percentToPxHeight);break;case "px":
                         break;default:
                         M *= 1 / n[G + "ToPx"];}
                   }switch (D) {case "+":
                       q = M + q;break;case "-":
                       q = M - q;break;case "*":
                       q = M * q;break;case "/":
                       q = M / q;}l[z] = { rootPropertyValue: B, startValue: M, currentValue: M, endValue: q, unitType: G, easing: $ }, b.debug && console.log("tweensContainer (" + z + "): " + JSON.stringify(l[z]), o);
                 } else b.debug && console.log("Skipping [" + I + "] due to a lack of browser support.");
               }l.element = o;
             }l.element && (S.Values.addClass(o, "velocity-animating"), R.push(l), "" === s.queue && (i(o).tweensContainer = l, i(o).opts = s), i(o).isAnimating = !0, V === w - 1 ? (b.State.calls.push([R, g, s, null, k.resolver]), b.State.isTicking === !1 && (b.State.isTicking = !0, c())) : V++);
           }var n,
               o = this,
               s = f.extend({}, b.defaults, v),
               l = {};switch (i(o) === a && b.init(o), parseFloat(s.delay) && s.queue !== !1 && f.queue(o, s.queue, function (e) {
             b.velocityQueueEntryFlag = !0, i(o).delayTimer = { setTimeout: setTimeout(e, parseFloat(s.delay)), next: e };
           }), s.duration.toString().toLowerCase()) {case "fast":
               s.duration = 200;break;case "normal":
               s.duration = h;break;case "slow":
               s.duration = 600;break;default:
               s.duration = parseFloat(s.duration) || 1;}b.mock !== !1 && (b.mock === !0 ? s.duration = s.delay = 1 : (s.duration *= parseFloat(b.mock) || 1, s.delay *= parseFloat(b.mock) || 1)), s.easing = u(s.easing, s.duration), s.begin && !m.isFunction(s.begin) && (s.begin = null), s.progress && !m.isFunction(s.progress) && (s.progress = null), s.complete && !m.isFunction(s.complete) && (s.complete = null), s.display !== a && null !== s.display && (s.display = s.display.toString().toLowerCase(), "auto" === s.display && (s.display = b.CSS.Values.getDisplayType(o))), s.visibility !== a && null !== s.visibility && (s.visibility = s.visibility.toString().toLowerCase()), s.mobileHA = s.mobileHA && b.State.isMobile && !b.State.isGingerbread, s.queue === !1 ? s.delay ? setTimeout(e, s.delay) : e() : f.queue(o, s.queue, function (t, r) {
             return r === !0 ? (k.promise && k.resolver(g), !0) : (b.velocityQueueEntryFlag = !0, void e(t));
           }), "" !== s.queue && "fx" !== s.queue || "inprogress" === f.queue(o)[0] || f.dequeue(o);
         }var s,
             l,
             d,
             g,
             y,
             v,
             x = arguments[0] && (arguments[0].p || f.isPlainObject(arguments[0].properties) && !arguments[0].properties.names || m.isString(arguments[0].properties));if (m.isWrapped(this) ? (s = !1, d = 0, g = this, l = this) : (s = !0, d = 1, g = x ? arguments[0].elements || arguments[0].e : arguments[0]), g = o(g)) {
           x ? (y = arguments[0].properties || arguments[0].p, v = arguments[0].options || arguments[0].o) : (y = arguments[d], v = arguments[d + 1]);var w = g.length,
               V = 0;if (!/^(stop|finish)$/i.test(y) && !f.isPlainObject(v)) {
             var C = d + 1;v = {};for (var T = C; T < arguments.length; T++) {
               m.isArray(arguments[T]) || !/^(fast|normal|slow)$/i.test(arguments[T]) && !/^\d/.test(arguments[T]) ? m.isString(arguments[T]) || m.isArray(arguments[T]) ? v.easing = arguments[T] : m.isFunction(arguments[T]) && (v.complete = arguments[T]) : v.duration = arguments[T];
             }
           }var k = { promise: null, resolver: null, rejecter: null };s && b.Promise && (k.promise = new b.Promise(function (e, t) {
             k.resolver = e, k.rejecter = t;
           }));var A;switch (y) {case "scroll":
               A = "scroll";break;case "reverse":
               A = "reverse";break;case "finish":case "stop":
               f.each(g, function (e, t) {
                 i(t) && i(t).delayTimer && (clearTimeout(i(t).delayTimer.setTimeout), i(t).delayTimer.next && i(t).delayTimer.next(), delete i(t).delayTimer);
               });var F = [];return f.each(b.State.calls, function (e, t) {
                 t && f.each(t[1], function (r, n) {
                   var o = v === a ? "" : v;return o === !0 || t[2].queue === o || v === a && t[2].queue === !1 ? void f.each(g, function (r, a) {
                     a === n && ((v === !0 || m.isString(v)) && (f.each(f.queue(a, m.isString(v) ? v : ""), function (e, t) {
                       m.isFunction(t) && t(null, !0);
                     }), f.queue(a, m.isString(v) ? v : "", [])), "stop" === y ? (i(a) && i(a).tweensContainer && o !== !1 && f.each(i(a).tweensContainer, function (e, t) {
                       t.endValue = t.currentValue;
                     }), F.push(e)) : "finish" === y && (t[2].duration = 1));
                   }) : !0;
                 });
               }), "stop" === y && (f.each(F, function (e, t) {
                 p(t, !0);
               }), k.promise && k.resolver(g)), e();default:
               if (!f.isPlainObject(y) || m.isEmptyObject(y)) {
                 if (m.isString(y) && b.Redirects[y]) {
                   var j = f.extend({}, v),
                       E = j.duration,
                       H = j.delay || 0;return j.backwards === !0 && (g = f.extend(!0, [], g).reverse()), f.each(g, function (e, t) {
                     parseFloat(j.stagger) ? j.delay = H + parseFloat(j.stagger) * e : m.isFunction(j.stagger) && (j.delay = H + j.stagger.call(t, e, w)), j.drag && (j.duration = parseFloat(E) || (/^(callout|transition)/.test(y) ? 1e3 : h), j.duration = Math.max(j.duration * (j.backwards ? 1 - e / w : (e + 1) / w), .75 * j.duration, 200)), b.Redirects[y].call(t, t, j || {}, e, w, g, k.promise ? k : a);
                   }), e();
                 }var N = "Velocity: First argument (" + y + ") was not a property map, a known action, or a registered redirect. Aborting.";return k.promise ? k.rejecter(new Error(N)) : console.log(N), e();
               }A = "start";}var L = { lastParent: null, lastPosition: null, lastFontSize: null, lastPercentToPxWidth: null, lastPercentToPxHeight: null, lastEmToPx: null, remToPx: null, vwToPx: null, vhToPx: null },
               R = [];f.each(g, function (e, t) {
             m.isNode(t) && n.call(t);
           });var z,
               j = f.extend({}, b.defaults, v);if (j.loop = parseInt(j.loop), z = 2 * j.loop - 1, j.loop) for (var O = 0; z > O; O++) {
             var q = { delay: j.delay, progress: j.progress };O === z - 1 && (q.display = j.display, q.visibility = j.visibility, q.complete = j.complete), P(g, "reverse", q);
           }return e();
         }
       };b = f.extend(P, b), b.animate = P;var w = t.requestAnimationFrame || g;return b.State.isMobile || r.hidden === a || r.addEventListener("visibilitychange", function () {
         r.hidden ? (w = function (e) {
           return setTimeout(function () {
             e(!0);
           }, 16);
         }, c()) : w = t.requestAnimationFrame || g;
       }), e.Velocity = b, e !== t && (e.fn.velocity = P, e.fn.velocity.defaults = b.defaults), f.each(["Down", "Up"], function (e, t) {
         b.Redirects["slide" + t] = function (e, r, n, o, i, s) {
           var l = f.extend({}, r),
               u = l.begin,
               c = l.complete,
               p = { height: "", marginTop: "", marginBottom: "", paddingTop: "", paddingBottom: "" },
               d = {};l.display === a && (l.display = "Down" === t ? "inline" === b.CSS.Values.getDisplayType(e) ? "inline-block" : "block" : "none"), l.begin = function () {
             u && u.call(i, i);for (var r in p) {
               d[r] = e.style[r];var a = b.CSS.getPropertyValue(e, r);p[r] = "Down" === t ? [a, 0] : [0, a];
             }d.overflow = e.style.overflow, e.style.overflow = "hidden";
           }, l.complete = function () {
             for (var t in d) {
               e.style[t] = d[t];
             }c && c.call(i, i), s && s.resolver(i);
           }, b(e, p, l);
         };
       }), f.each(["In", "Out"], function (e, t) {
         b.Redirects["fade" + t] = function (e, r, n, o, i, s) {
           var l = f.extend({}, r),
               u = { opacity: "In" === t ? 1 : 0 },
               c = l.complete;l.complete = n !== o - 1 ? l.begin = null : function () {
             c && c.call(i, i), s && s.resolver(i);
           }, l.display === a && (l.display = "In" === t ? "auto" : "none"), b(this, u, l);
         };
       }), b;
     }(window.jQuery || window.Zepto || window, window, document);
   }));
   ;!function (a, b, c, d) {
     "use strict";
     function k(a, b, c) {
       return setTimeout(q(a, c), b);
     }function l(a, b, c) {
       return Array.isArray(a) ? (m(a, c[b], c), !0) : !1;
     }function m(a, b, c) {
       var e;if (a) if (a.forEach) a.forEach(b, c);else if (a.length !== d) for (e = 0; e < a.length;) {
         b.call(c, a[e], e, a), e++;
       } else for (e in a) {
         a.hasOwnProperty(e) && b.call(c, a[e], e, a);
       }
     }function n(a, b, c) {
       for (var e = Object.keys(b), f = 0; f < e.length;) {
         (!c || c && a[e[f]] === d) && (a[e[f]] = b[e[f]]), f++;
       }return a;
     }function o(a, b) {
       return n(a, b, !0);
     }function p(a, b, c) {
       var e,
           d = b.prototype;e = a.prototype = Object.create(d), e.constructor = a, e._super = d, c && n(e, c);
     }function q(a, b) {
       return function () {
         return a.apply(b, arguments);
       };
     }function r(a, b) {
       return typeof a == g ? a.apply(b ? b[0] || d : d, b) : a;
     }function s(a, b) {
       return a === d ? b : a;
     }function t(a, b, c) {
       m(x(b), function (b) {
         a.addEventListener(b, c, !1);
       });
     }function u(a, b, c) {
       m(x(b), function (b) {
         a.removeEventListener(b, c, !1);
       });
     }function v(a, b) {
       for (; a;) {
         if (a == b) return !0;a = a.parentNode;
       }return !1;
     }function w(a, b) {
       return a.indexOf(b) > -1;
     }function x(a) {
       return a.trim().split(/\s+/g);
     }function y(a, b, c) {
       if (a.indexOf && !c) return a.indexOf(b);for (var d = 0; d < a.length;) {
         if (c && a[d][c] == b || !c && a[d] === b) return d;d++;
       }return -1;
     }function z(a) {
       return Array.prototype.slice.call(a, 0);
     }function A(a, b, c) {
       for (var d = [], e = [], f = 0; f < a.length;) {
         var g = b ? a[f][b] : a[f];y(e, g) < 0 && d.push(a[f]), e[f] = g, f++;
       }return c && (d = b ? d.sort(function (a, c) {
         return a[b] > c[b];
       }) : d.sort()), d;
     }function B(a, b) {
       for (var c, f, g = b[0].toUpperCase() + b.slice(1), h = 0; h < e.length;) {
         if (c = e[h], f = c ? c + g : b, f in a) return f;h++;
       }return d;
     }function D() {
       return C++;
     }function E(a) {
       var b = a.ownerDocument;return b.defaultView || b.parentWindow;
     }function ab(a, b) {
       var c = this;this.manager = a, this.callback = b, this.element = a.element, this.target = a.options.inputTarget, this.domHandler = function (b) {
         r(a.options.enable, [a]) && c.handler(b);
       }, this.init();
     }function bb(a) {
       var b,
           c = a.options.inputClass;return b = c ? c : H ? wb : I ? Eb : G ? Gb : rb, new b(a, cb);
     }function cb(a, b, c) {
       var d = c.pointers.length,
           e = c.changedPointers.length,
           f = b & O && 0 === d - e,
           g = b & (Q | R) && 0 === d - e;c.isFirst = !!f, c.isFinal = !!g, f && (a.session = {}), c.eventType = b, db(a, c), a.emit("hammer.input", c), a.recognize(c), a.session.prevInput = c;
     }function db(a, b) {
       var c = a.session,
           d = b.pointers,
           e = d.length;c.firstInput || (c.firstInput = gb(b)), e > 1 && !c.firstMultiple ? c.firstMultiple = gb(b) : 1 === e && (c.firstMultiple = !1);var f = c.firstInput,
           g = c.firstMultiple,
           h = g ? g.center : f.center,
           i = b.center = hb(d);b.timeStamp = j(), b.deltaTime = b.timeStamp - f.timeStamp, b.angle = lb(h, i), b.distance = kb(h, i), eb(c, b), b.offsetDirection = jb(b.deltaX, b.deltaY), b.scale = g ? nb(g.pointers, d) : 1, b.rotation = g ? mb(g.pointers, d) : 0, fb(c, b);var k = a.element;v(b.srcEvent.target, k) && (k = b.srcEvent.target), b.target = k;
     }function eb(a, b) {
       var c = b.center,
           d = a.offsetDelta || {},
           e = a.prevDelta || {},
           f = a.prevInput || {};(b.eventType === O || f.eventType === Q) && (e = a.prevDelta = { x: f.deltaX || 0, y: f.deltaY || 0 }, d = a.offsetDelta = { x: c.x, y: c.y }), b.deltaX = e.x + (c.x - d.x), b.deltaY = e.y + (c.y - d.y);
     }function fb(a, b) {
       var f,
           g,
           h,
           j,
           c = a.lastInterval || b,
           e = b.timeStamp - c.timeStamp;if (b.eventType != R && (e > N || c.velocity === d)) {
         var k = c.deltaX - b.deltaX,
             l = c.deltaY - b.deltaY,
             m = ib(e, k, l);g = m.x, h = m.y, f = i(m.x) > i(m.y) ? m.x : m.y, j = jb(k, l), a.lastInterval = b;
       } else f = c.velocity, g = c.velocityX, h = c.velocityY, j = c.direction;b.velocity = f, b.velocityX = g, b.velocityY = h, b.direction = j;
     }function gb(a) {
       for (var b = [], c = 0; c < a.pointers.length;) {
         b[c] = { clientX: h(a.pointers[c].clientX), clientY: h(a.pointers[c].clientY) }, c++;
       }return { timeStamp: j(), pointers: b, center: hb(b), deltaX: a.deltaX, deltaY: a.deltaY };
     }function hb(a) {
       var b = a.length;if (1 === b) return { x: h(a[0].clientX), y: h(a[0].clientY) };for (var c = 0, d = 0, e = 0; b > e;) {
         c += a[e].clientX, d += a[e].clientY, e++;
       }return { x: h(c / b), y: h(d / b) };
     }function ib(a, b, c) {
       return { x: b / a || 0, y: c / a || 0 };
     }function jb(a, b) {
       return a === b ? S : i(a) >= i(b) ? a > 0 ? T : U : b > 0 ? V : W;
     }function kb(a, b, c) {
       c || (c = $);var d = b[c[0]] - a[c[0]],
           e = b[c[1]] - a[c[1]];return Math.sqrt(d * d + e * e);
     }function lb(a, b, c) {
       c || (c = $);var d = b[c[0]] - a[c[0]],
           e = b[c[1]] - a[c[1]];return 180 * Math.atan2(e, d) / Math.PI;
     }function mb(a, b) {
       return lb(b[1], b[0], _) - lb(a[1], a[0], _);
     }function nb(a, b) {
       return kb(b[0], b[1], _) / kb(a[0], a[1], _);
     }function rb() {
       this.evEl = pb, this.evWin = qb, this.allow = !0, this.pressed = !1, ab.apply(this, arguments);
     }function wb() {
       this.evEl = ub, this.evWin = vb, ab.apply(this, arguments), this.store = this.manager.session.pointerEvents = [];
     }function Ab() {
       this.evTarget = yb, this.evWin = zb, this.started = !1, ab.apply(this, arguments);
     }function Bb(a, b) {
       var c = z(a.touches),
           d = z(a.changedTouches);return b & (Q | R) && (c = A(c.concat(d), "identifier", !0)), [c, d];
     }function Eb() {
       this.evTarget = Db, this.targetIds = {}, ab.apply(this, arguments);
     }function Fb(a, b) {
       var c = z(a.touches),
           d = this.targetIds;if (b & (O | P) && 1 === c.length) return d[c[0].identifier] = !0, [c, c];var e,
           f,
           g = z(a.changedTouches),
           h = [],
           i = this.target;if (f = c.filter(function (a) {
         return v(a.target, i);
       }), b === O) for (e = 0; e < f.length;) {
         d[f[e].identifier] = !0, e++;
       }for (e = 0; e < g.length;) {
         d[g[e].identifier] && h.push(g[e]), b & (Q | R) && delete d[g[e].identifier], e++;
       }return h.length ? [A(f.concat(h), "identifier", !0), h] : void 0;
     }function Gb() {
       ab.apply(this, arguments);var a = q(this.handler, this);this.touch = new Eb(this.manager, a), this.mouse = new rb(this.manager, a);
     }function Pb(a, b) {
       this.manager = a, this.set(b);
     }function Qb(a) {
       if (w(a, Mb)) return Mb;var b = w(a, Nb),
           c = w(a, Ob);return b && c ? Nb + " " + Ob : b || c ? b ? Nb : Ob : w(a, Lb) ? Lb : Kb;
     }function Yb(a) {
       this.id = D(), this.manager = null, this.options = o(a || {}, this.defaults), this.options.enable = s(this.options.enable, !0), this.state = Rb, this.simultaneous = {}, this.requireFail = [];
     }function Zb(a) {
       return a & Wb ? "cancel" : a & Ub ? "end" : a & Tb ? "move" : a & Sb ? "start" : "";
     }function $b(a) {
       return a == W ? "down" : a == V ? "up" : a == T ? "left" : a == U ? "right" : "";
     }function _b(a, b) {
       var c = b.manager;return c ? c.get(a) : a;
     }function ac() {
       Yb.apply(this, arguments);
     }function bc() {
       ac.apply(this, arguments), this.pX = null, this.pY = null;
     }function cc() {
       ac.apply(this, arguments);
     }function dc() {
       Yb.apply(this, arguments), this._timer = null, this._input = null;
     }function ec() {
       ac.apply(this, arguments);
     }function fc() {
       ac.apply(this, arguments);
     }function gc() {
       Yb.apply(this, arguments), this.pTime = !1, this.pCenter = !1, this._timer = null, this._input = null, this.count = 0;
     }function hc(a, b) {
       return b = b || {}, b.recognizers = s(b.recognizers, hc.defaults.preset), new kc(a, b);
     }function kc(a, b) {
       b = b || {}, this.options = o(b, hc.defaults), this.options.inputTarget = this.options.inputTarget || a, this.handlers = {}, this.session = {}, this.recognizers = [], this.element = a, this.input = bb(this), this.touchAction = new Pb(this, this.options.touchAction), lc(this, !0), m(b.recognizers, function (a) {
         var b = this.add(new a[0](a[1]));a[2] && b.recognizeWith(a[2]), a[3] && b.requireFailure(a[3]);
       }, this);
     }function lc(a, b) {
       var c = a.element;m(a.options.cssProps, function (a, d) {
         c.style[B(c.style, d)] = b ? a : "";
       });
     }function mc(a, c) {
       var d = b.createEvent("Event");d.initEvent(a, !0, !0), d.gesture = c, c.target.dispatchEvent(d);
     }var e = ["", "webkit", "moz", "MS", "ms", "o"],
         f = b.createElement("div"),
         g = "function",
         h = Math.round,
         i = Math.abs,
         j = Date.now,
         C = 1,
         F = /mobile|tablet|ip(ad|hone|od)|android/i,
         G = "ontouchstart" in a,
         H = B(a, "PointerEvent") !== d,
         I = G && F.test(navigator.userAgent),
         J = "touch",
         K = "pen",
         L = "mouse",
         M = "kinect",
         N = 25,
         O = 1,
         P = 2,
         Q = 4,
         R = 8,
         S = 1,
         T = 2,
         U = 4,
         V = 8,
         W = 16,
         X = T | U,
         Y = V | W,
         Z = X | Y,
         $ = ["x", "y"],
         _ = ["clientX", "clientY"];ab.prototype = { handler: function () {}, init: function () {
         this.evEl && t(this.element, this.evEl, this.domHandler), this.evTarget && t(this.target, this.evTarget, this.domHandler), this.evWin && t(E(this.element), this.evWin, this.domHandler);
       }, destroy: function () {
         this.evEl && u(this.element, this.evEl, this.domHandler), this.evTarget && u(this.target, this.evTarget, this.domHandler), this.evWin && u(E(this.element), this.evWin, this.domHandler);
       } };var ob = { mousedown: O, mousemove: P, mouseup: Q },
         pb = "mousedown",
         qb = "mousemove mouseup";p(rb, ab, { handler: function (a) {
         var b = ob[a.type];b & O && 0 === a.button && (this.pressed = !0), b & P && 1 !== a.which && (b = Q), this.pressed && this.allow && (b & Q && (this.pressed = !1), this.callback(this.manager, b, { pointers: [a], changedPointers: [a], pointerType: L, srcEvent: a }));
       } });var sb = { pointerdown: O, pointermove: P, pointerup: Q, pointercancel: R, pointerout: R },
         tb = { 2: J, 3: K, 4: L, 5: M },
         ub = "pointerdown",
         vb = "pointermove pointerup pointercancel";a.MSPointerEvent && (ub = "MSPointerDown", vb = "MSPointerMove MSPointerUp MSPointerCancel"), p(wb, ab, { handler: function (a) {
         var b = this.store,
             c = !1,
             d = a.type.toLowerCase().replace("ms", ""),
             e = sb[d],
             f = tb[a.pointerType] || a.pointerType,
             g = f == J,
             h = y(b, a.pointerId, "pointerId");e & O && (0 === a.button || g) ? 0 > h && (b.push(a), h = b.length - 1) : e & (Q | R) && (c = !0), 0 > h || (b[h] = a, this.callback(this.manager, e, { pointers: b, changedPointers: [a], pointerType: f, srcEvent: a }), c && b.splice(h, 1));
       } });var xb = { touchstart: O, touchmove: P, touchend: Q, touchcancel: R },
         yb = "touchstart",
         zb = "touchstart touchmove touchend touchcancel";p(Ab, ab, { handler: function (a) {
         var b = xb[a.type];if (b === O && (this.started = !0), this.started) {
           var c = Bb.call(this, a, b);b & (Q | R) && 0 === c[0].length - c[1].length && (this.started = !1), this.callback(this.manager, b, { pointers: c[0], changedPointers: c[1], pointerType: J, srcEvent: a });
         }
       } });var Cb = { touchstart: O, touchmove: P, touchend: Q, touchcancel: R },
         Db = "touchstart touchmove touchend touchcancel";p(Eb, ab, { handler: function (a) {
         var b = Cb[a.type],
             c = Fb.call(this, a, b);c && this.callback(this.manager, b, { pointers: c[0], changedPointers: c[1], pointerType: J, srcEvent: a });
       } }), p(Gb, ab, { handler: function (a, b, c) {
         var d = c.pointerType == J,
             e = c.pointerType == L;if (d) this.mouse.allow = !1;else if (e && !this.mouse.allow) return;b & (Q | R) && (this.mouse.allow = !0), this.callback(a, b, c);
       }, destroy: function () {
         this.touch.destroy(), this.mouse.destroy();
       } });var Hb = B(f.style, "touchAction"),
         Ib = Hb !== d,
         Jb = "compute",
         Kb = "auto",
         Lb = "manipulation",
         Mb = "none",
         Nb = "pan-x",
         Ob = "pan-y";Pb.prototype = { set: function (a) {
         a == Jb && (a = this.compute()), Ib && (this.manager.element.style[Hb] = a), this.actions = a.toLowerCase().trim();
       }, update: function () {
         this.set(this.manager.options.touchAction);
       }, compute: function () {
         var a = [];return m(this.manager.recognizers, function (b) {
           r(b.options.enable, [b]) && (a = a.concat(b.getTouchAction()));
         }), Qb(a.join(" "));
       }, preventDefaults: function (a) {
         if (!Ib) {
           var b = a.srcEvent,
               c = a.offsetDirection;if (this.manager.session.prevented) return b.preventDefault(), void 0;var d = this.actions,
               e = w(d, Mb),
               f = w(d, Ob),
               g = w(d, Nb);return e || f && c & X || g && c & Y ? this.preventSrc(b) : void 0;
         }
       }, preventSrc: function (a) {
         this.manager.session.prevented = !0, a.preventDefault();
       } };var Rb = 1,
         Sb = 2,
         Tb = 4,
         Ub = 8,
         Vb = Ub,
         Wb = 16,
         Xb = 32;Yb.prototype = { defaults: {}, set: function (a) {
         return n(this.options, a), this.manager && this.manager.touchAction.update(), this;
       }, recognizeWith: function (a) {
         if (l(a, "recognizeWith", this)) return this;var b = this.simultaneous;return a = _b(a, this), b[a.id] || (b[a.id] = a, a.recognizeWith(this)), this;
       }, dropRecognizeWith: function (a) {
         return l(a, "dropRecognizeWith", this) ? this : (a = _b(a, this), delete this.simultaneous[a.id], this);
       }, requireFailure: function (a) {
         if (l(a, "requireFailure", this)) return this;var b = this.requireFail;return a = _b(a, this), -1 === y(b, a) && (b.push(a), a.requireFailure(this)), this;
       }, dropRequireFailure: function (a) {
         if (l(a, "dropRequireFailure", this)) return this;a = _b(a, this);var b = y(this.requireFail, a);return b > -1 && this.requireFail.splice(b, 1), this;
       }, hasRequireFailures: function () {
         return this.requireFail.length > 0;
       }, canRecognizeWith: function (a) {
         return !!this.simultaneous[a.id];
       }, emit: function (a) {
         function d(d) {
           b.manager.emit(b.options.event + (d ? Zb(c) : ""), a);
         }var b = this,
             c = this.state;Ub > c && d(!0), d(), c >= Ub && d(!0);
       }, tryEmit: function (a) {
         return this.canEmit() ? this.emit(a) : (this.state = Xb, void 0);
       }, canEmit: function () {
         for (var a = 0; a < this.requireFail.length;) {
           if (!(this.requireFail[a].state & (Xb | Rb))) return !1;a++;
         }return !0;
       }, recognize: function (a) {
         var b = n({}, a);return r(this.options.enable, [this, b]) ? (this.state & (Vb | Wb | Xb) && (this.state = Rb), this.state = this.process(b), this.state & (Sb | Tb | Ub | Wb) && this.tryEmit(b), void 0) : (this.reset(), this.state = Xb, void 0);
       }, process: function () {}, getTouchAction: function () {}, reset: function () {} }, p(ac, Yb, { defaults: { pointers: 1 }, attrTest: function (a) {
         var b = this.options.pointers;return 0 === b || a.pointers.length === b;
       }, process: function (a) {
         var b = this.state,
             c = a.eventType,
             d = b & (Sb | Tb),
             e = this.attrTest(a);return d && (c & R || !e) ? b | Wb : d || e ? c & Q ? b | Ub : b & Sb ? b | Tb : Sb : Xb;
       } }), p(bc, ac, { defaults: { event: "pan", threshold: 10, pointers: 1, direction: Z }, getTouchAction: function () {
         var a = this.options.direction,
             b = [];return a & X && b.push(Ob), a & Y && b.push(Nb), b;
       }, directionTest: function (a) {
         var b = this.options,
             c = !0,
             d = a.distance,
             e = a.direction,
             f = a.deltaX,
             g = a.deltaY;return e & b.direction || (b.direction & X ? (e = 0 === f ? S : 0 > f ? T : U, c = f != this.pX, d = Math.abs(a.deltaX)) : (e = 0 === g ? S : 0 > g ? V : W, c = g != this.pY, d = Math.abs(a.deltaY))), a.direction = e, c && d > b.threshold && e & b.direction;
       }, attrTest: function (a) {
         return ac.prototype.attrTest.call(this, a) && (this.state & Sb || !(this.state & Sb) && this.directionTest(a));
       }, emit: function (a) {
         this.pX = a.deltaX, this.pY = a.deltaY;var b = $b(a.direction);b && this.manager.emit(this.options.event + b, a), this._super.emit.call(this, a);
       } }), p(cc, ac, { defaults: { event: "pinch", threshold: 0, pointers: 2 }, getTouchAction: function () {
         return [Mb];
       }, attrTest: function (a) {
         return this._super.attrTest.call(this, a) && (Math.abs(a.scale - 1) > this.options.threshold || this.state & Sb);
       }, emit: function (a) {
         if (this._super.emit.call(this, a), 1 !== a.scale) {
           var b = a.scale < 1 ? "in" : "out";this.manager.emit(this.options.event + b, a);
         }
       } }), p(dc, Yb, { defaults: { event: "press", pointers: 1, time: 500, threshold: 5 }, getTouchAction: function () {
         return [Kb];
       }, process: function (a) {
         var b = this.options,
             c = a.pointers.length === b.pointers,
             d = a.distance < b.threshold,
             e = a.deltaTime > b.time;if (this._input = a, !d || !c || a.eventType & (Q | R) && !e) this.reset();else if (a.eventType & O) this.reset(), this._timer = k(function () {
           this.state = Vb, this.tryEmit();
         }, b.time, this);else if (a.eventType & Q) return Vb;return Xb;
       }, reset: function () {
         clearTimeout(this._timer);
       }, emit: function (a) {
         this.state === Vb && (a && a.eventType & Q ? this.manager.emit(this.options.event + "up", a) : (this._input.timeStamp = j(), this.manager.emit(this.options.event, this._input)));
       } }), p(ec, ac, { defaults: { event: "rotate", threshold: 0, pointers: 2 }, getTouchAction: function () {
         return [Mb];
       }, attrTest: function (a) {
         return this._super.attrTest.call(this, a) && (Math.abs(a.rotation) > this.options.threshold || this.state & Sb);
       } }), p(fc, ac, { defaults: { event: "swipe", threshold: 10, velocity: .65, direction: X | Y, pointers: 1 }, getTouchAction: function () {
         return bc.prototype.getTouchAction.call(this);
       }, attrTest: function (a) {
         var c,
             b = this.options.direction;return b & (X | Y) ? c = a.velocity : b & X ? c = a.velocityX : b & Y && (c = a.velocityY), this._super.attrTest.call(this, a) && b & a.direction && a.distance > this.options.threshold && i(c) > this.options.velocity && a.eventType & Q;
       }, emit: function (a) {
         var b = $b(a.direction);b && this.manager.emit(this.options.event + b, a), this.manager.emit(this.options.event, a);
       } }), p(gc, Yb, { defaults: { event: "tap", pointers: 1, taps: 1, interval: 300, time: 250, threshold: 2, posThreshold: 10 }, getTouchAction: function () {
         return [Lb];
       }, process: function (a) {
         var b = this.options,
             c = a.pointers.length === b.pointers,
             d = a.distance < b.threshold,
             e = a.deltaTime < b.time;if (this.reset(), a.eventType & O && 0 === this.count) return this.failTimeout();if (d && e && c) {
           if (a.eventType != Q) return this.failTimeout();var f = this.pTime ? a.timeStamp - this.pTime < b.interval : !0,
               g = !this.pCenter || kb(this.pCenter, a.center) < b.posThreshold;this.pTime = a.timeStamp, this.pCenter = a.center, g && f ? this.count += 1 : this.count = 1, this._input = a;var h = this.count % b.taps;if (0 === h) return this.hasRequireFailures() ? (this._timer = k(function () {
             this.state = Vb, this.tryEmit();
           }, b.interval, this), Sb) : Vb;
         }return Xb;
       }, failTimeout: function () {
         return this._timer = k(function () {
           this.state = Xb;
         }, this.options.interval, this), Xb;
       }, reset: function () {
         clearTimeout(this._timer);
       }, emit: function () {
         this.state == Vb && (this._input.tapCount = this.count, this.manager.emit(this.options.event, this._input));
       } }), hc.VERSION = "2.0.4", hc.defaults = { domEvents: !1, touchAction: Jb, enable: !0, inputTarget: null, inputClass: null, preset: [[ec, { enable: !1 }], [cc, { enable: !1 }, ["rotate"]], [fc, { direction: X }], [bc, { direction: X }, ["swipe"]], [gc], [gc, { event: "doubletap", taps: 2 }, ["tap"]], [dc]], cssProps: { userSelect: "default", touchSelect: "none", touchCallout: "none", contentZooming: "none", userDrag: "none", tapHighlightColor: "rgba(0,0,0,0)" } };var ic = 1,
         jc = 2;kc.prototype = { set: function (a) {
         return n(this.options, a), a.touchAction && this.touchAction.update(), a.inputTarget && (this.input.destroy(), this.input.target = a.inputTarget, this.input.init()), this;
       }, stop: function (a) {
         this.session.stopped = a ? jc : ic;
       }, recognize: function (a) {
         var b = this.session;if (!b.stopped) {
           this.touchAction.preventDefaults(a);var c,
               d = this.recognizers,
               e = b.curRecognizer;(!e || e && e.state & Vb) && (e = b.curRecognizer = null);for (var f = 0; f < d.length;) {
             c = d[f], b.stopped === jc || e && c != e && !c.canRecognizeWith(e) ? c.reset() : c.recognize(a), !e && c.state & (Sb | Tb | Ub) && (e = b.curRecognizer = c), f++;
           }
         }
       }, get: function (a) {
         if (a instanceof Yb) return a;for (var b = this.recognizers, c = 0; c < b.length; c++) {
           if (b[c].options.event == a) return b[c];
         }return null;
       }, add: function (a) {
         if (l(a, "add", this)) return this;var b = this.get(a.options.event);return b && this.remove(b), this.recognizers.push(a), a.manager = this, this.touchAction.update(), a;
       }, remove: function (a) {
         if (l(a, "remove", this)) return this;var b = this.recognizers;return a = this.get(a), b.splice(y(b, a), 1), this.touchAction.update(), this;
       }, on: function (a, b) {
         var c = this.handlers;return m(x(a), function (a) {
           c[a] = c[a] || [], c[a].push(b);
         }), this;
       }, off: function (a, b) {
         var c = this.handlers;return m(x(a), function (a) {
           b ? c[a].splice(y(c[a], b), 1) : delete c[a];
         }), this;
       }, emit: function (a, b) {
         this.options.domEvents && mc(a, b);var c = this.handlers[a] && this.handlers[a].slice();if (c && c.length) {
           b.type = a, b.preventDefault = function () {
             b.srcEvent.preventDefault();
           };for (var d = 0; d < c.length;) {
             c[d](b), d++;
           }
         }
       }, destroy: function () {
         this.element && lc(this, !1), this.handlers = {}, this.session = {}, this.input.destroy(), this.element = null;
       } }, n(hc, { INPUT_START: O, INPUT_MOVE: P, INPUT_END: Q, INPUT_CANCEL: R, STATE_POSSIBLE: Rb, STATE_BEGAN: Sb, STATE_CHANGED: Tb, STATE_ENDED: Ub, STATE_RECOGNIZED: Vb, STATE_CANCELLED: Wb, STATE_FAILED: Xb, DIRECTION_NONE: S, DIRECTION_LEFT: T, DIRECTION_RIGHT: U, DIRECTION_UP: V, DIRECTION_DOWN: W, DIRECTION_HORIZONTAL: X, DIRECTION_VERTICAL: Y, DIRECTION_ALL: Z, Manager: kc, Input: ab, TouchAction: Pb, TouchInput: Eb, MouseInput: rb, PointerEventInput: wb, TouchMouseInput: Gb, SingleTouchInput: Ab, Recognizer: Yb, AttrRecognizer: ac, Tap: gc, Pan: bc, Swipe: fc, Pinch: cc, Rotate: ec, Press: dc, on: t, off: u, each: m, merge: o, extend: n, inherit: p, bindFn: q, prefixed: B }), "function" == g && __webpack_require__(7) ? !(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
       return hc;
     }.call(exports, __webpack_require__, exports, module),
                   __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)) : "undefined" != typeof module && module.exports ? module.exports = hc : a[c] = hc;
   }(window, document, "Hammer");;(function (factory) {
     if (true) {
       !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(0), __webpack_require__(8)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
                   __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
                   (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
                   __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
     } else if (typeof exports === 'object') {
       factory(require('jquery'), require('hammerjs'));
     } else {
       factory(jQuery, Hammer);
     }
   })(function ($, Hammer) {
     function hammerify(el, options) {
       var $el = $(el);
       if (!$el.data("hammer")) {
         $el.data("hammer", new Hammer($el[0], options));
       }
     }
   
     $.fn.hammer = function (options) {
       return this.each(function () {
         hammerify(this, options);
       });
     };
   
     // extend the emit method to also trigger jQuery events
     Hammer.Manager.prototype.emit = function (originalEmit) {
       return function (type, data) {
         originalEmit.call(this, type, data);
         $(this.element).trigger({
           type: type,
           gesture: data
         });
       };
     }(Hammer.Manager.prototype.emit);
   });
   ; // Required for Meteor package, the use of window prevents export by Meteor
   (function (window) {
     if (window.Package) {
       Materialize = {};
     } else {
       window.Materialize = {};
     }
   })(window);
   
   /*
    * raf.js
    * https://github.com/ngryman/raf.js
    *
    * original requestAnimationFrame polyfill by Erik Möller
    * inspired from paul_irish gist and post
    *
    * Copyright (c) 2013 ngryman
    * Licensed under the MIT license.
    */
   (function (window) {
     var lastTime = 0,
         vendors = ['webkit', 'moz'],
         requestAnimationFrame = window.requestAnimationFrame,
         cancelAnimationFrame = window.cancelAnimationFrame,
         i = vendors.length;
   
     // try to un-prefix existing raf
     while (--i >= 0 && !requestAnimationFrame) {
       requestAnimationFrame = window[vendors[i] + 'RequestAnimationFrame'];
       cancelAnimationFrame = window[vendors[i] + 'CancelRequestAnimationFrame'];
     }
   
     // polyfill with setTimeout fallback
     // heavily inspired from @darius gist mod: https://gist.github.com/paulirish/1579671#comment-837945
     if (!requestAnimationFrame || !cancelAnimationFrame) {
       requestAnimationFrame = function (callback) {
         var now = +Date.now(),
             nextTime = Math.max(lastTime + 16, now);
         return setTimeout(function () {
           callback(lastTime = nextTime);
         }, nextTime - now);
       };
   
       cancelAnimationFrame = clearTimeout;
     }
   
     // export to window
     window.requestAnimationFrame = requestAnimationFrame;
     window.cancelAnimationFrame = cancelAnimationFrame;
   })(window);
   
   /**
    * Generate approximated selector string for a jQuery object
    * @param {jQuery} obj  jQuery object to be parsed
    * @returns {string}
    */
   Materialize.objectSelectorString = function (obj) {
     var tagStr = obj.prop('tagName') || '';
     var idStr = obj.attr('id') || '';
     var classStr = obj.attr('class') || '';
     return (tagStr + idStr + classStr).replace(/\s/g, '');
   };
   
   // Unique Random ID
   Materialize.guid = function () {
     function s4() {
       return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
     }
     return function () {
       return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
     };
   }();
   
   /**
    * Escapes hash from special characters
    * @param {string} hash  String returned from this.hash
    * @returns {string}
    */
   Materialize.escapeHash = function (hash) {
     return hash.replace(/(:|\.|\[|\]|,|=)/g, "\\$1");
   };
   
   Materialize.elementOrParentIsFixed = function (element) {
     var $element = $(element);
     var $checkElements = $element.add($element.parents());
     var isFixed = false;
     $checkElements.each(function () {
       if ($(this).css("position") === "fixed") {
         isFixed = true;
         return false;
       }
     });
     return isFixed;
   };
   
   /**
    * Get time in ms
    * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
    * @type {function}
    * @return {number}
    */
   var getTime = Date.now || function () {
     return new Date().getTime();
   };
   
   /**
    * Returns a function, that, when invoked, will only be triggered at most once
    * during a given window of time. Normally, the throttled function will run
    * as much as it can, without ever going more than once per `wait` duration;
    * but if you'd like to disable the execution on the leading edge, pass
    * `{leading: false}`. To disable execution on the trailing edge, ditto.
    * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
    * @param {function} func
    * @param {number} wait
    * @param {Object=} options
    * @returns {Function}
    */
   Materialize.throttle = function (func, wait, options) {
     var context, args, result;
     var timeout = null;
     var previous = 0;
     options || (options = {});
     var later = function () {
       previous = options.leading === false ? 0 : getTime();
       timeout = null;
       result = func.apply(context, args);
       context = args = null;
     };
     return function () {
       var now = getTime();
       if (!previous && options.leading === false) previous = now;
       var remaining = wait - (now - previous);
       context = this;
       args = arguments;
       if (remaining <= 0) {
         clearTimeout(timeout);
         timeout = null;
         previous = now;
         result = func.apply(context, args);
         context = args = null;
       } else if (!timeout && options.trailing !== false) {
         timeout = setTimeout(later, remaining);
       }
       return result;
     };
   };
   
   // Velocity has conflicts when loaded with jQuery, this will check for it
   // First, check if in noConflict mode
   var Vel;
   if (jQuery) {
     Vel = jQuery.Velocity;
   } else if ($) {
     Vel = $.Velocity;
   } else {
     Vel = Velocity;
   }
   ;(function ($) {
     $.fn.collapsible = function (options, methodParam) {
       var defaults = {
         accordion: undefined,
         onOpen: undefined,
         onClose: undefined
       };
   
       var methodName = options;
       options = $.extend(defaults, options);
   
       return this.each(function () {
   
         var $this = $(this);
   
         var $panel_headers = $(this).find('> li > .collapsible-header');
   
         var collapsible_type = $this.data("collapsible");
   
         /****************
         Helper Functions
         ****************/
   
         // Accordion Open
         function accordionOpen(object) {
           $panel_headers = $this.find('> li > .collapsible-header');
           if (object.hasClass('active')) {
             object.parent().addClass('active');
           } else {
             object.parent().removeClass('active');
           }
           if (object.parent().hasClass('active')) {
             object.siblings('.collapsible-body').stop(true, false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function () {
                 $(this).css('height', '');
               } });
           } else {
             object.siblings('.collapsible-body').stop(true, false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function () {
                 $(this).css('height', '');
               } });
           }
   
           $panel_headers.not(object).removeClass('active').parent().removeClass('active');
   
           // Close previously open accordion elements.
           $panel_headers.not(object).parent().children('.collapsible-body').stop(true, false).each(function () {
             if ($(this).is(':visible')) {
               $(this).slideUp({
                 duration: 350,
                 easing: "easeOutQuart",
                 queue: false,
                 complete: function () {
                   $(this).css('height', '');
                   execCallbacks($(this).siblings('.collapsible-header'));
                 }
               });
             }
           });
         }
   
         // Expandable Open
         function expandableOpen(object) {
           if (object.hasClass('active')) {
             object.parent().addClass('active');
           } else {
             object.parent().removeClass('active');
           }
           if (object.parent().hasClass('active')) {
             object.siblings('.collapsible-body').stop(true, false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function () {
                 $(this).css('height', '');
               } });
           } else {
             object.siblings('.collapsible-body').stop(true, false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function () {
                 $(this).css('height', '');
               } });
           }
         }
   
         // Open collapsible. object: .collapsible-header
         function collapsibleOpen(object, noToggle) {
           if (!noToggle) {
             object.toggleClass('active');
           }
   
           if (options.accordion || collapsible_type === "accordion" || collapsible_type === undefined) {
             // Handle Accordion
             accordionOpen(object);
           } else {
             // Handle Expandables
             expandableOpen(object);
           }
   
           execCallbacks(object);
         }
   
         // Handle callbacks
         function execCallbacks(object) {
           if (object.hasClass('active')) {
             if (typeof options.onOpen === "function") {
               options.onOpen.call(this, object.parent());
             }
           } else {
             if (typeof options.onClose === "function") {
               options.onClose.call(this, object.parent());
             }
           }
         }
   
         /**
          * Check if object is children of panel header
          * @param  {Object}  object Jquery object
          * @return {Boolean} true if it is children
          */
         function isChildrenOfPanelHeader(object) {
   
           var panelHeader = getPanelHeader(object);
   
           return panelHeader.length > 0;
         }
   
         /**
          * Get panel header from a children element
          * @param  {Object} object Jquery object
          * @return {Object} panel header object
          */
         function getPanelHeader(object) {
   
           return object.closest('li > .collapsible-header');
         }
   
         // Turn off any existing event handlers
         function removeEventHandlers() {
           $this.off('click.collapse', '> li > .collapsible-header');
         }
   
         /*****  End Helper Functions  *****/
   
         // Methods
         if (methodName === 'destroy') {
           removeEventHandlers();
           return;
         } else if (methodParam >= 0 && methodParam < $panel_headers.length) {
           var $curr_header = $panel_headers.eq(methodParam);
           if ($curr_header.length && (methodName === 'open' || methodName === 'close' && $curr_header.hasClass('active'))) {
             collapsibleOpen($curr_header);
           }
           return;
         }
   
         removeEventHandlers();
   
         // Add click handler to only direct collapsible header children
         $this.on('click.collapse', '> li > .collapsible-header', function (e) {
           var element = $(e.target);
   
           if (isChildrenOfPanelHeader(element)) {
             element = getPanelHeader(element);
           }
   
           collapsibleOpen(element);
         });
   
         // Open first active
         if (options.accordion || collapsible_type === "accordion" || collapsible_type === undefined) {
           // Handle Accordion
           collapsibleOpen($panel_headers.filter('.active').first(), true);
         } else {
           // Handle Expandables
           $panel_headers.filter('.active').each(function () {
             collapsibleOpen($(this), true);
           });
         }
       });
     };
   
     $(document).ready(function () {
       $('.collapsible').collapsible();
     });
   })(jQuery);;(function ($) {
   
     // Add posibility to scroll to selected option
     // usefull for select for example
     $.fn.scrollTo = function (elem) {
       $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top);
       return this;
     };
   
     $.fn.dropdown = function (options) {
       var defaults = {
         inDuration: 300,
         outDuration: 225,
         constrainWidth: true, // Constrains width of dropdown to the activator
         hover: false,
         gutter: 0, // Spacing from edge
         belowOrigin: false,
         alignment: 'left',
         stopPropagation: false
       };
   
       // Open dropdown.
       if (options === "open") {
         this.each(function () {
           $(this).trigger('open');
         });
         return false;
       }
   
       // Close dropdown.
       if (options === "close") {
         this.each(function () {
           $(this).trigger('close');
         });
         return false;
       }
   
       this.each(function () {
         var origin = $(this);
         var curr_options = $.extend({}, defaults, options);
         var isFocused = false;
   
         // Dropdown menu
         var activates = $("#" + origin.attr('data-activates'));
   
         function updateOptions() {
           if (origin.data('induration') !== undefined) curr_options.inDuration = origin.data('induration');
           if (origin.data('outduration') !== undefined) curr_options.outDuration = origin.data('outduration');
           if (origin.data('constrainwidth') !== undefined) curr_options.constrainWidth = origin.data('constrainwidth');
           if (origin.data('hover') !== undefined) curr_options.hover = origin.data('hover');
           if (origin.data('gutter') !== undefined) curr_options.gutter = origin.data('gutter');
           if (origin.data('beloworigin') !== undefined) curr_options.belowOrigin = origin.data('beloworigin');
           if (origin.data('alignment') !== undefined) curr_options.alignment = origin.data('alignment');
           if (origin.data('stoppropagation') !== undefined) curr_options.stopPropagation = origin.data('stoppropagation');
         }
   
         updateOptions();
   
         // Attach dropdown to its activator
         origin.after(activates);
   
         /*
           Helper function to position and resize dropdown.
           Used in hover and click handler.
         */
         function placeDropdown(eventType) {
           // Check for simultaneous focus and click events.
           if (eventType === 'focus') {
             isFocused = true;
           }
   
           // Check html data attributes
           updateOptions();
   
           // Set Dropdown state
           activates.addClass('active');
           origin.addClass('active');
   
           var originWidth = origin[0].getBoundingClientRect().width;
   
           // Constrain width
           if (curr_options.constrainWidth === true) {
             activates.css('width', originWidth);
           } else {
             activates.css('white-space', 'nowrap');
           }
   
           // Offscreen detection
           var windowHeight = window.innerHeight;
           var originHeight = origin.innerHeight();
           var offsetLeft = origin.offset().left;
           var offsetTop = origin.offset().top - $(window).scrollTop();
           var currAlignment = curr_options.alignment;
           var gutterSpacing = 0;
           var leftPosition = 0;
   
           // Below Origin
           var verticalOffset = 0;
           if (curr_options.belowOrigin === true) {
             verticalOffset = originHeight;
           }
   
           // Check for scrolling positioned container.
           var scrollYOffset = 0;
           var scrollXOffset = 0;
           var wrapper = origin.parent();
           if (!wrapper.is('body')) {
             if (wrapper[0].scrollHeight > wrapper[0].clientHeight) {
               scrollYOffset = wrapper[0].scrollTop;
             }
             if (wrapper[0].scrollWidth > wrapper[0].clientWidth) {
               scrollXOffset = wrapper[0].scrollLeft;
             }
           }
   
           if (offsetLeft + activates.innerWidth() > $(window).width()) {
             // Dropdown goes past screen on right, force right alignment
             currAlignment = 'right';
           } else if (offsetLeft - activates.innerWidth() + origin.innerWidth() < 0) {
             // Dropdown goes past screen on left, force left alignment
             currAlignment = 'left';
           }
           // Vertical bottom offscreen detection
           if (offsetTop + activates.innerHeight() > windowHeight) {
             // If going upwards still goes offscreen, just crop height of dropdown.
             if (offsetTop + originHeight - activates.innerHeight() < 0) {
               var adjustedHeight = windowHeight - offsetTop - verticalOffset;
               activates.css('max-height', adjustedHeight);
             } else {
               // Flow upwards.
               if (!verticalOffset) {
                 verticalOffset += originHeight;
               }
               verticalOffset -= activates.innerHeight();
             }
           }
   
           // Handle edge alignment
           if (currAlignment === 'left') {
             gutterSpacing = curr_options.gutter;
             leftPosition = origin.position().left + gutterSpacing;
           } else if (currAlignment === 'right') {
             // Material icons fix
             activates.stop(true, true).css({
               opacity: 0,
               left: 0
             });
   
             var offsetRight = origin.position().left + originWidth - activates.width();
             gutterSpacing = -curr_options.gutter;
             leftPosition = offsetRight + gutterSpacing;
           }
   
           // Position dropdown
           activates.css({
             position: 'absolute',
             top: origin.position().top + verticalOffset + scrollYOffset,
             left: leftPosition + scrollXOffset
           });
   
           // Show dropdown
           activates.slideDown({
             queue: false,
             duration: curr_options.inDuration,
             easing: 'easeOutCubic',
             complete: function () {
               $(this).css('height', '');
             }
           }).animate({ opacity: 1 }, { queue: false, duration: curr_options.inDuration, easing: 'easeOutSine' });
   
           // Add click close handler to document
           setTimeout(function () {
             $(document).on('click.' + activates.attr('id'), function (e) {
               hideDropdown();
               $(document).off('click.' + activates.attr('id'));
             });
           }, 0);
         }
   
         function hideDropdown() {
           // Check for simultaneous focus and click events.
           isFocused = false;
           activates.fadeOut(curr_options.outDuration);
           activates.removeClass('active');
           origin.removeClass('active');
           $(document).off('click.' + activates.attr('id'));
           setTimeout(function () {
             activates.css('max-height', '');
           }, curr_options.outDuration);
         }
   
         // Hover
         if (curr_options.hover) {
           var open = false;
           origin.off('click.' + origin.attr('id'));
           // Hover handler to show dropdown
           origin.on('mouseenter', function (e) {
             // Mouse over
             if (open === false) {
               placeDropdown();
               open = true;
             }
           });
           origin.on('mouseleave', function (e) {
             // If hover on origin then to something other than dropdown content, then close
             var toEl = e.toElement || e.relatedTarget; // added browser compatibility for target element
             if (!$(toEl).closest('.dropdown-content').is(activates)) {
               activates.stop(true, true);
               hideDropdown();
               open = false;
             }
           });
   
           activates.on('mouseleave', function (e) {
             // Mouse out
             var toEl = e.toElement || e.relatedTarget;
             if (!$(toEl).closest('.dropdown-button').is(origin)) {
               activates.stop(true, true);
               hideDropdown();
               open = false;
             }
           });
   
           // Click
         } else {
           // Click handler to show dropdown
           origin.off('click.' + origin.attr('id'));
           origin.on('click.' + origin.attr('id'), function (e) {
             if (!isFocused) {
               if (origin[0] == e.currentTarget && !origin.hasClass('active') && $(e.target).closest('.dropdown-content').length === 0) {
                 e.preventDefault(); // Prevents button click from moving window
                 if (curr_options.stopPropagation) {
                   e.stopPropagation();
                 }
                 placeDropdown('click');
               }
               // If origin is clicked and menu is open, close menu
               else if (origin.hasClass('active')) {
                   hideDropdown();
                   $(document).off('click.' + activates.attr('id'));
                 }
             }
           });
         } // End else
   
         // Listen to open and close event - useful for select component
         origin.on('open', function (e, eventType) {
           placeDropdown(eventType);
         });
         origin.on('close', hideDropdown);
       });
     }; // End dropdown plugin
   
     $(document).ready(function () {
       $('.dropdown-button').dropdown();
     });
   })(jQuery);
   ;(function ($) {
     'use strict';
   
     var _defaults = {
       opacity: 0.5,
       inDuration: 250,
       outDuration: 250,
       ready: undefined,
       complete: undefined,
       dismissible: true,
       startingTop: '4%',
       endingTop: '10%'
     };
   
     /**
      * @class
      *
      */
   
     var Modal = function () {
       /**
        * Construct Modal instance and set up overlay
        * @constructor
        * @param {jQuery} $el
        * @param {Object} options
        */
       function Modal($el, options) {
         _classCallCheck(this, Modal);
   
         // If exists, destroy and reinitialize
         if (!!$el[0].M_Modal) {
           $el[0].M_Modal.destroy();
         }
   
         /**
          * The jQuery element
          * @type {jQuery}
          */
         this.$el = $el;
   
         /**
          * Options for the modal
          * @member Modal#options
          * @prop {Number} [opacity=0.5] - Opacity of the modal overlay
          * @prop {Number} [inDuration=250] - Length in ms of enter transition
          * @prop {Number} [outDuration=250] - Length in ms of exit transition
          * @prop {Function} ready - Callback function called when modal is finished entering
          * @prop {Function} complete - Callback function called when modal is finished exiting
          * @prop {Boolean} [dismissible=true] - Allow modal to be dismissed by keyboard or overlay click
          * @prop {String} [startingTop='4%'] - startingTop
          * @prop {String} [endingTop='10%'] - endingTop
          */
         this.options = $.extend({}, Modal.defaults, options);
   
         /**
          * Describes open/close state of modal
          * @type {Boolean}
          */
         this.isOpen = false;
   
         this.$el[0].M_Modal = this;
         this.id = $el.attr('id');
         this.openingTrigger = undefined;
         this.$overlay = $('<div class="modal-overlay"></div>');
   
         Modal._increment++;
         Modal._count++;
         this.$overlay[0].style.zIndex = 1000 + Modal._increment * 2;
         this.$el[0].style.zIndex = 1000 + Modal._increment * 2 + 1;
         this.setupEventHandlers();
       }
   
       _createClass(Modal, [{
         key: 'getInstance',
   
   
         /**
          * Get Instance
          */
         value: function getInstance() {
           return this;
         }
   
         /**
          * Teardown component
          */
   
       }, {
         key: 'destroy',
         value: function destroy() {
           this.removeEventHandlers();
           this.$el[0].removeAttribute('style');
           if (!!this.$overlay[0].parentNode) {
             this.$overlay[0].parentNode.removeChild(this.$overlay[0]);
           }
           this.$el[0].M_Modal = undefined;
           Modal._count--;
         }
   
         /**
          * Setup Event Handlers
          */
   
       }, {
         key: 'setupEventHandlers',
         value: function setupEventHandlers() {
           this.handleOverlayClickBound = this.handleOverlayClick.bind(this);
           this.handleModalCloseClickBound = this.handleModalCloseClick.bind(this);
   
           if (Modal._count === 1) {
             document.addEventListener('click', this.handleTriggerClick);
           }
           this.$overlay[0].addEventListener('click', this.handleOverlayClickBound);
           this.$el[0].addEventListener('click', this.handleModalCloseClickBound);
         }
   
         /**
          * Remove Event Handlers
          */
   
       }, {
         key: 'removeEventHandlers',
         value: function removeEventHandlers() {
           if (Modal._count === 0) {
             document.removeEventListener('click', this.handleTriggerClick);
           }
           this.$overlay[0].removeEventListener('click', this.handleOverlayClickBound);
           this.$el[0].removeEventListener('click', this.handleModalCloseClickBound);
         }
   
         /**
          * Handle Trigger Click
          * @param {Event} e
          */
   
       }, {
         key: 'handleTriggerClick',
         value: function handleTriggerClick(e) {
           var $trigger = $(e.target).closest('.modal-trigger');
           if (e.target && $trigger.length) {
             var modalId = $trigger[0].getAttribute('href');
             if (modalId) {
               modalId = modalId.slice(1);
             } else {
               modalId = $trigger[0].getAttribute('data-target');
             }
             var modalInstance = document.getElementById(modalId).M_Modal;
             if (modalInstance) {
               modalInstance.open($trigger);
             }
             e.preventDefault();
           }
         }
   
         /**
          * Handle Overlay Click
          */
   
       }, {
         key: 'handleOverlayClick',
         value: function handleOverlayClick() {
           if (this.options.dismissible) {
             this.close();
           }
         }
   
         /**
          * Handle Modal Close Click
          * @param {Event} e
          */
   
       }, {
         key: 'handleModalCloseClick',
         value: function handleModalCloseClick(e) {
           var $closeTrigger = $(e.target).closest('.modal-close');
           if (e.target && $closeTrigger.length) {
             this.close();
           }
         }
   
         /**
          * Handle Keydown
          * @param {Event} e
          */
   
       }, {
         key: 'handleKeydown',
         value: function handleKeydown(e) {
           // ESC key
           if (e.keyCode === 27 && this.options.dismissible) {
             this.close();
           }
         }
   
         /**
          * Animate in modal
          */
   
       }, {
         key: 'animateIn',
         value: function animateIn() {
           var _this = this;
   
           // Set initial styles
           $.extend(this.$el[0].style, {
             display: 'block',
             opacity: 0
           });
           $.extend(this.$overlay[0].style, {
             display: 'block',
             opacity: 0
           });
   
           // Animate overlay
           Vel(this.$overlay[0], { opacity: this.options.opacity }, { duration: this.options.inDuration, queue: false, ease: 'easeOutCubic' });
   
           // Define modal animation options
           var enterVelocityOptions = {
             duration: this.options.inDuration,
             queue: false,
             ease: 'easeOutCubic',
             // Handle modal ready callback
             complete: function () {
               if (typeof _this.options.ready === 'function') {
                 _this.options.ready.call(_this, _this.$el, _this.openingTrigger);
               }
             }
           };
   
           // Bottom sheet animation
           if (this.$el[0].classList.contains('bottom-sheet')) {
             Vel(this.$el[0], { bottom: 0, opacity: 1 }, enterVelocityOptions);
   
             // Normal modal animation
           } else {
             Vel.hook(this.$el[0], 'scaleX', 0.7);
             this.$el[0].style.top = this.options.startingTop;
             Vel(this.$el[0], { top: this.options.endingTop, opacity: 1, scaleX: 1 }, enterVelocityOptions);
           }
         }
   
         /**
          * Animate out modal
          */
   
       }, {
         key: 'animateOut',
         value: function animateOut() {
           var _this2 = this;
   
           // Animate overlay
           Vel(this.$overlay[0], { opacity: 0 }, { duration: this.options.outDuration, queue: false, ease: 'easeOutQuart' });
   
           // Define modal animation options
           var exitVelocityOptions = {
             duration: this.options.outDuration,
             queue: false,
             ease: 'easeOutCubic',
             // Handle modal ready callback
             complete: function () {
               _this2.$el[0].style.display = 'none';
               // Call complete callback
               if (typeof _this2.options.complete === 'function') {
                 _this2.options.complete.call(_this2, _this2.$el);
               }
               _this2.$overlay[0].remove();
             }
           };
   
           // Bottom sheet animation
           if (this.$el[0].classList.contains('bottom-sheet')) {
             Vel(this.$el[0], { bottom: '-100%', opacity: 0 }, exitVelocityOptions);
   
             // Normal modal animation
           } else {
             Vel(this.$el[0], { top: this.options.startingTop, opacity: 0, scaleX: 0.7 }, exitVelocityOptions);
           }
         }
   
         /**
          * Open Modal
          * @param {jQuery} [$trigger]
          */
   
       }, {
         key: 'open',
         value: function open($trigger) {
           if (this.isOpen) {
             return;
           }
   
           this.isOpen = true;
           var body = document.body;
           body.style.overflow = 'hidden';
           this.$el[0].classList.add('open');
           body.appendChild(this.$overlay[0]);
   
           // Set opening trigger, undefined indicates modal was opened by javascript
           this.openingTrigger = !!$trigger ? $trigger : undefined;
   
           if (this.options.dismissible) {
             this.handleKeydownBound = this.handleKeydown.bind(this);
             document.addEventListener('keydown', this.handleKeydownBound);
           }
   
           this.animateIn();
   
           return this;
         }
   
         /**
          * Close Modal
          */
   
       }, {
         key: 'close',
         value: function close() {
           if (!this.isOpen) {
             return;
           }
   
           this.isOpen = false;
           this.$el[0].classList.remove('open');
           document.body.style.overflow = null;
   
           if (this.options.dismissible) {
             document.removeEventListener('keydown', this.handleKeydownBound);
           }
   
           this.animateOut();
   
           return this;
         }
       }], [{
         key: 'init',
         value: function init($els, options) {
           var arr = [];
           $els.each(function () {
             arr.push(new Modal($(this), options));
           });
           return arr;
         }
       }, {
         key: 'defaults',
         get: function () {
           return _defaults;
         }
       }]);
   
       return Modal;
     }();
   
     /**
      * @static
      * @memberof Modal
      */
   
   
     Modal._increment = 0;
   
     /**
      * @static
      * @memberof Modal
      */
     Modal._count = 0;
   
     window.Materialize.Modal = Modal;
   
     $.fn.modal = function (methodOrOptions) {
       // Call plugin method if valid method name is passed in
       if (Modal.prototype[methodOrOptions]) {
         // Getter methods
         if (methodOrOptions.slice(0, 3) === 'get') {
           return this.first()[0].M_Modal[methodOrOptions]();
   
           // Void methods
         } else {
           return this.each(function () {
             this.M_Modal[methodOrOptions]();
           });
         }
   
         // Initialize plugin if options or no argument is passed in
       } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
         Modal.init(this, arguments[0]);
         return this;
   
         // Return error if an unrecognized  method name is passed in
       } else {
         $.error('Method ' + methodOrOptions + ' does not exist on jQuery.modal');
       }
     };
   })(jQuery);
   ;(function ($) {
   
     $.fn.materialbox = function () {
   
       return this.each(function () {
   
         if ($(this).hasClass('initialized')) {
           return;
         }
   
         $(this).addClass('initialized');
   
         var overlayActive = false;
         var doneAnimating = true;
         var inDuration = 275;
         var outDuration = 200;
         var origin = $(this);
         var placeholder = $('<div></div>').addClass('material-placeholder');
         var originalWidth = 0;
         var originalHeight = 0;
         var ancestorsChanged;
         var ancestor;
         var originInlineStyles = origin.attr('style');
         origin.wrap(placeholder);
   
         // Start click handler
         origin.on('click', function () {
           var placeholder = origin.parent('.material-placeholder');
           var windowWidth = window.innerWidth;
           var windowHeight = window.innerHeight;
           var originalWidth = origin.width();
           var originalHeight = origin.height();
   
           // If already modal, return to original
           if (doneAnimating === false) {
             returnToOriginal();
             return false;
           } else if (overlayActive && doneAnimating === true) {
             returnToOriginal();
             return false;
           }
   
           // Set states
           doneAnimating = false;
           origin.addClass('active');
           overlayActive = true;
   
           // Set positioning for placeholder
           placeholder.css({
             width: placeholder[0].getBoundingClientRect().width,
             height: placeholder[0].getBoundingClientRect().height,
             position: 'relative',
             top: 0,
             left: 0
           });
   
           // Find ancestor with overflow: hidden; and remove it
           ancestorsChanged = undefined;
           ancestor = placeholder[0].parentNode;
           var count = 0;
           while (ancestor !== null && !$(ancestor).is(document)) {
             var curr = $(ancestor);
             if (curr.css('overflow') !== 'visible') {
               curr.css('overflow', 'visible');
               if (ancestorsChanged === undefined) {
                 ancestorsChanged = curr;
               } else {
                 ancestorsChanged = ancestorsChanged.add(curr);
               }
             }
             ancestor = ancestor.parentNode;
           }
   
           // Set css on origin
           origin.css({
             position: 'absolute',
             'z-index': 1000,
             'will-change': 'left, top, width, height'
           }).data('width', originalWidth).data('height', originalHeight);
   
           // Add overlay
           var overlay = $('<div id="materialbox-overlay"></div>').css({
             opacity: 0
           }).click(function () {
             if (doneAnimating === true) returnToOriginal();
           });
   
           // Put before in origin image to preserve z-index layering.
           origin.before(overlay);
   
           // Set dimensions if needed
           var overlayOffset = overlay[0].getBoundingClientRect();
           overlay.css({
             width: windowWidth,
             height: windowHeight,
             left: -1 * overlayOffset.left,
             top: -1 * overlayOffset.top
           });
   
           // Animate Overlay
           overlay.velocity({ opacity: 1 }, { duration: inDuration, queue: false, easing: 'easeOutQuad' });
   
           // Add and animate caption if it exists
           if (origin.data('caption') !== "") {
             var $photo_caption = $('<div class="materialbox-caption"></div>');
             $photo_caption.text(origin.data('caption'));
             $('body').append($photo_caption);
             $photo_caption.css({ "display": "inline" });
             $photo_caption.velocity({ opacity: 1 }, { duration: inDuration, queue: false, easing: 'easeOutQuad' });
           }
   
           // Resize Image
           var ratio = 0;
           var widthPercent = originalWidth / windowWidth;
           var heightPercent = originalHeight / windowHeight;
           var newWidth = 0;
           var newHeight = 0;
   
           if (widthPercent > heightPercent) {
             ratio = originalHeight / originalWidth;
             newWidth = windowWidth * 0.9;
             newHeight = windowWidth * 0.9 * ratio;
           } else {
             ratio = originalWidth / originalHeight;
             newWidth = windowHeight * 0.9 * ratio;
             newHeight = windowHeight * 0.9;
           }
   
           // Animate image + set z-index
           if (origin.hasClass('responsive-img')) {
             origin.velocity({ 'max-width': newWidth, 'width': originalWidth }, { duration: 0, queue: false,
               complete: function () {
                 origin.css({ left: 0, top: 0 }).velocity({
                   height: newHeight,
                   width: newWidth,
                   left: $(document).scrollLeft() + windowWidth / 2 - origin.parent('.material-placeholder').offset().left - newWidth / 2,
                   top: $(document).scrollTop() + windowHeight / 2 - origin.parent('.material-placeholder').offset().top - newHeight / 2
                 }, {
                   duration: inDuration,
                   queue: false,
                   easing: 'easeOutQuad',
                   complete: function () {
                     doneAnimating = true;
                   }
                 });
               } // End Complete
             }); // End Velocity
           } else {
             origin.css('left', 0).css('top', 0).velocity({
               height: newHeight,
               width: newWidth,
               left: $(document).scrollLeft() + windowWidth / 2 - origin.parent('.material-placeholder').offset().left - newWidth / 2,
               top: $(document).scrollTop() + windowHeight / 2 - origin.parent('.material-placeholder').offset().top - newHeight / 2
             }, {
               duration: inDuration,
               queue: false,
               easing: 'easeOutQuad',
               complete: function () {
                 doneAnimating = true;
               }
             }); // End Velocity
           }
   
           // Handle Exit triggers
           $(window).on('scroll.materialbox', function () {
             if (overlayActive) {
               returnToOriginal();
             }
           });
   
           $(window).on('resize.materialbox', function () {
             if (overlayActive) {
               returnToOriginal();
             }
           });
   
           $(document).on('keyup.materialbox', function (e) {
             // ESC key
             if (e.keyCode === 27 && doneAnimating === true && overlayActive) {
               returnToOriginal();
             }
           });
         }); // End click handler
   
   
         // This function returns the modaled image to the original spot
         function returnToOriginal() {
   
           doneAnimating = false;
   
           var placeholder = origin.parent('.material-placeholder');
           var windowWidth = window.innerWidth;
           var windowHeight = window.innerHeight;
           var originalWidth = origin.data('width');
           var originalHeight = origin.data('height');
   
           origin.velocity("stop", true);
           $('#materialbox-overlay').velocity("stop", true);
           $('.materialbox-caption').velocity("stop", true);
   
           // disable exit handlers
           $(window).off('scroll.materialbox');
           $(document).off('keyup.materialbox');
           $(window).off('resize.materialbox');
   
           $('#materialbox-overlay').velocity({ opacity: 0 }, {
             duration: outDuration, // Delay prevents animation overlapping
             queue: false, easing: 'easeOutQuad',
             complete: function () {
               // Remove Overlay
               overlayActive = false;
               $(this).remove();
             }
           });
   
           // Resize Image
           origin.velocity({
             width: originalWidth,
             height: originalHeight,
             left: 0,
             top: 0
           }, {
             duration: outDuration,
             queue: false, easing: 'easeOutQuad',
             complete: function () {
               placeholder.css({
                 height: '',
                 width: '',
                 position: '',
                 top: '',
                 left: ''
               });
   
               origin.removeAttr('style');
               origin.attr('style', originInlineStyles);
   
               // Remove class
               origin.removeClass('active');
               doneAnimating = true;
   
               // Remove overflow overrides on ancestors
               if (ancestorsChanged) {
                 ancestorsChanged.css('overflow', '');
               }
             }
           });
   
           // Remove Caption + reset css settings on image
           $('.materialbox-caption').velocity({ opacity: 0 }, {
             duration: outDuration, // Delay prevents animation overlapping
             queue: false, easing: 'easeOutQuad',
             complete: function () {
               $(this).remove();
             }
           });
         }
       });
     };
   
     $(document).ready(function () {
       $('.materialboxed').materialbox();
     });
   })(jQuery);
   ;(function ($) {
   
     $.fn.parallax = function () {
       var window_width = $(window).width();
       // Parallax Scripts
       return this.each(function (i) {
         var $this = $(this);
         $this.addClass('parallax');
   
         function updateParallax(initial) {
           var container_height;
           if (window_width < 601) {
             container_height = $this.height() > 0 ? $this.height() : $this.children("img").height();
           } else {
             container_height = $this.height() > 0 ? $this.height() : 500;
           }
           var $img = $this.children("img").first();
           var img_height = $img.height();
           var parallax_dist = img_height - container_height;
           var bottom = $this.offset().top + container_height;
           var top = $this.offset().top;
           var scrollTop = $(window).scrollTop();
           var windowHeight = window.innerHeight;
           var windowBottom = scrollTop + windowHeight;
           var percentScrolled = (windowBottom - top) / (container_height + windowHeight);
           var parallax = Math.round(parallax_dist * percentScrolled);
   
           if (initial) {
             $img.css('display', 'block');
           }
           if (bottom > scrollTop && top < scrollTop + windowHeight) {
             $img.css('transform', "translate3D(-50%," + parallax + "px, 0)");
           }
         }
   
         // Wait for image load
         $this.children("img").one("load", function () {
           updateParallax(true);
         }).each(function () {
           if (this.complete) $(this).trigger("load");
         });
   
         $(window).scroll(function () {
           window_width = $(window).width();
           updateParallax(false);
         });
   
         $(window).resize(function () {
           window_width = $(window).width();
           updateParallax(false);
         });
       });
     };
   })(jQuery);
   ;(function ($) {
   
     var methods = {
       init: function (options) {
         var defaults = {
           onShow: null,
           swipeable: false,
           responsiveThreshold: Infinity // breakpoint for swipeable
         };
         options = $.extend(defaults, options);
         var namespace = Materialize.objectSelectorString($(this));
   
         return this.each(function (i) {
   
           var uniqueNamespace = namespace + i;
   
           // For each set of tabs, we want to keep track of
           // which tab is active and its associated content
           var $this = $(this),
               window_width = $(window).width();
   
           var $active,
               $content,
               $links = $this.find('li.tab a'),
               $tabs_width = $this.width(),
               $tabs_content = $(),
               $tabs_wrapper,
               $tab_width = Math.max($tabs_width, $this[0].scrollWidth) / $links.length,
               $indicator,
               index = prev_index = 0,
               clicked = false,
               clickedTimeout,
               transition = 300;
   
           // Finds right attribute for indicator based on active tab.
           // el: jQuery Object
           var calcRightPos = function (el) {
             return Math.ceil($tabs_width - el.position().left - el[0].getBoundingClientRect().width - $this.scrollLeft());
           };
   
           // Finds left attribute for indicator based on active tab.
           // el: jQuery Object
           var calcLeftPos = function (el) {
             return Math.floor(el.position().left + $this.scrollLeft());
           };
   
           // Animates Indicator to active tab.
           // prev_index: Number
           var animateIndicator = function (prev_index) {
             if (index - prev_index >= 0) {
               $indicator.velocity({ "right": calcRightPos($active) }, { duration: transition, queue: false, easing: 'easeOutQuad' });
               $indicator.velocity({ "left": calcLeftPos($active) }, { duration: transition, queue: false, easing: 'easeOutQuad', delay: 90 });
             } else {
               $indicator.velocity({ "left": calcLeftPos($active) }, { duration: transition, queue: false, easing: 'easeOutQuad' });
               $indicator.velocity({ "right": calcRightPos($active) }, { duration: transition, queue: false, easing: 'easeOutQuad', delay: 90 });
             }
           };
   
           // Change swipeable according to responsive threshold
           if (options.swipeable) {
             if (window_width > options.responsiveThreshold) {
               options.swipeable = false;
             }
           }
   
           // If the location.hash matches one of the links, use that as the active tab.
           $active = $($links.filter('[href="' + location.hash + '"]'));
   
           // If no match is found, use the first link or any with class 'active' as the initial active tab.
           if ($active.length === 0) {
             $active = $(this).find('li.tab a.active').first();
           }
           if ($active.length === 0) {
             $active = $(this).find('li.tab a').first();
           }
   
           $active.addClass('active');
           index = $links.index($active);
           if (index < 0) {
             index = 0;
           }
   
           if ($active[0] !== undefined) {
             $content = $($active[0].hash);
             $content.addClass('active');
           }
   
           // append indicator then set indicator width to tab width
           if (!$this.find('.indicator').length) {
             $this.append('<li class="indicator"></li>');
           }
           $indicator = $this.find('.indicator');
   
           // we make sure that the indicator is at the end of the tabs
           $this.append($indicator);
   
           if ($this.is(":visible")) {
             // $indicator.css({"right": $tabs_width - ((index + 1) * $tab_width)});
             // $indicator.css({"left": index * $tab_width});
             setTimeout(function () {
               $indicator.css({ "right": calcRightPos($active) });
               $indicator.css({ "left": calcLeftPos($active) });
             }, 0);
           }
           $(window).off('resize.tabs-' + uniqueNamespace).on('resize.tabs-' + uniqueNamespace, function () {
             $tabs_width = $this.width();
             $tab_width = Math.max($tabs_width, $this[0].scrollWidth) / $links.length;
             if (index < 0) {
               index = 0;
             }
             if ($tab_width !== 0 && $tabs_width !== 0) {
               $indicator.css({ "right": calcRightPos($active) });
               $indicator.css({ "left": calcLeftPos($active) });
             }
           });
   
           // Initialize Tabs Content.
           if (options.swipeable) {
             // TODO: Duplicate calls with swipeable? handle multiple div wrapping.
             $links.each(function () {
               var $curr_content = $(Materialize.escapeHash(this.hash));
               $curr_content.addClass('carousel-item');
               $tabs_content = $tabs_content.add($curr_content);
             });
             $tabs_wrapper = $tabs_content.wrapAll('<div class="tabs-content carousel"></div>');
             $tabs_content.css('display', '');
             $('.tabs-content.carousel').carousel({
               fullWidth: true,
               noWrap: true,
               onCycleTo: function (item) {
                 if (!clicked) {
                   var prev_index = index;
                   index = $tabs_wrapper.index(item);
                   $active.removeClass('active');
                   $active = $links.eq(index);
                   $active.addClass('active');
                   animateIndicator(prev_index);
                   if (typeof options.onShow === "function") {
                     options.onShow.call($this[0], $content);
                   }
                 }
               }
             });
           } else {
             // Hide the remaining content
             $links.not($active).each(function () {
               $(Materialize.escapeHash(this.hash)).hide();
             });
           }
   
           // Bind the click event handler
           $this.off('click.tabs').on('click.tabs', 'a', function (e) {
             if ($(this).parent().hasClass('disabled')) {
               e.preventDefault();
               return;
             }
   
             // Act as regular link if target attribute is specified.
             if (!!$(this).attr("target")) {
               return;
             }
   
             clicked = true;
             $tabs_width = $this.width();
             $tab_width = Math.max($tabs_width, $this[0].scrollWidth) / $links.length;
   
             // Make the old tab inactive.
             $active.removeClass('active');
             var $oldContent = $content;
   
             // Update the variables with the new link and content
             $active = $(this);
             $content = $(Materialize.escapeHash(this.hash));
             $links = $this.find('li.tab a');
             var activeRect = $active.position();
   
             // Make the tab active.
             $active.addClass('active');
             prev_index = index;
             index = $links.index($(this));
             if (index < 0) {
               index = 0;
             }
             // Change url to current tab
             // window.location.hash = $active.attr('href');
   
             // Swap content
             if (options.swipeable) {
               if ($tabs_content.length) {
                 $tabs_content.carousel('set', index, function () {
                   if (typeof options.onShow === "function") {
                     options.onShow.call($this[0], $content);
                   }
                 });
               }
             } else {
               if ($content !== undefined) {
                 $content.show();
                 $content.addClass('active');
                 if (typeof options.onShow === "function") {
                   options.onShow.call(this, $content);
                 }
               }
   
               if ($oldContent !== undefined && !$oldContent.is($content)) {
                 $oldContent.hide();
                 $oldContent.removeClass('active');
               }
             }
   
             // Reset clicked state
             clickedTimeout = setTimeout(function () {
               clicked = false;
             }, transition);
   
             // Update indicator
             animateIndicator(prev_index);
   
             // Prevent the anchor's default click action
             e.preventDefault();
           });
         });
       },
       select_tab: function (id) {
         this.find('a[href="#' + id + '"]').trigger('click');
       }
     };
   
     $.fn.tabs = function (methodOrOptions) {
       if (methods[methodOrOptions]) {
         return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
       } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
         // Default to "init"
         return methods.init.apply(this, arguments);
       } else {
         $.error('Method ' + methodOrOptions + ' does not exist on jQuery.tabs');
       }
     };
   
     $(document).ready(function () {
       $('ul.tabs').tabs();
     });
   })(jQuery);
   ;(function ($) {
     $.fn.tooltip = function (options) {
       var timeout = null,
           margin = 5;
   
       // Defaults
       var defaults = {
         delay: 350,
         tooltip: '',
         position: 'bottom',
         html: false
       };
   
       // Remove tooltip from the activator
       if (options === "remove") {
         this.each(function () {
           $('#' + $(this).attr('data-tooltip-id')).remove();
           $(this).removeAttr('data-tooltip-id');
           $(this).off('mouseenter.tooltip mouseleave.tooltip');
         });
         return false;
       }
   
       options = $.extend(defaults, options);
   
       return this.each(function () {
         var tooltipId = Materialize.guid();
         var origin = $(this);
   
         // Destroy old tooltip
         if (origin.attr('data-tooltip-id')) {
           $('#' + origin.attr('data-tooltip-id')).remove();
         }
   
         origin.attr('data-tooltip-id', tooltipId);
   
         // Get attributes.
         var allowHtml, tooltipDelay, tooltipPosition, tooltipText, tooltipEl, backdrop;
         var setAttributes = function () {
           allowHtml = origin.attr('data-html') ? origin.attr('data-html') === 'true' : options.html;
           tooltipDelay = origin.attr('data-delay');
           tooltipDelay = tooltipDelay === undefined || tooltipDelay === '' ? options.delay : tooltipDelay;
           tooltipPosition = origin.attr('data-position');
           tooltipPosition = tooltipPosition === undefined || tooltipPosition === '' ? options.position : tooltipPosition;
           tooltipText = origin.attr('data-tooltip');
           tooltipText = tooltipText === undefined || tooltipText === '' ? options.tooltip : tooltipText;
         };
         setAttributes();
   
         var renderTooltipEl = function () {
           var tooltip = $('<div class="material-tooltip"></div>');
   
           // Create Text span
           if (allowHtml) {
             tooltipText = $('<span></span>').html(tooltipText);
           } else {
             tooltipText = $('<span></span>').text(tooltipText);
           }
   
           // Create tooltip
           tooltip.append(tooltipText).appendTo($('body')).attr('id', tooltipId);
   
           // Create backdrop
           backdrop = $('<div class="backdrop"></div>');
           backdrop.appendTo(tooltip);
           return tooltip;
         };
         tooltipEl = renderTooltipEl();
   
         // Destroy previously binded events
         origin.off('mouseenter.tooltip mouseleave.tooltip');
         // Mouse In
         var started = false,
             timeoutRef;
         origin.on({ 'mouseenter.tooltip': function (e) {
             var showTooltip = function () {
               setAttributes();
               started = true;
               tooltipEl.velocity('stop');
               backdrop.velocity('stop');
               tooltipEl.css({ visibility: 'visible', left: '0px', top: '0px' });
   
               // Tooltip positioning
               var originWidth = origin.outerWidth();
               var originHeight = origin.outerHeight();
               var tooltipHeight = tooltipEl.outerHeight();
               var tooltipWidth = tooltipEl.outerWidth();
               var tooltipVerticalMovement = '0px';
               var tooltipHorizontalMovement = '0px';
               var backdropOffsetWidth = backdrop[0].offsetWidth;
               var backdropOffsetHeight = backdrop[0].offsetHeight;
               var scaleXFactor = 8;
               var scaleYFactor = 8;
               var scaleFactor = 0;
               var targetTop, targetLeft, newCoordinates;
   
               if (tooltipPosition === "top") {
                 // Top Position
                 targetTop = origin.offset().top - tooltipHeight - margin;
                 targetLeft = origin.offset().left + originWidth / 2 - tooltipWidth / 2;
                 newCoordinates = repositionWithinScreen(targetLeft, targetTop, tooltipWidth, tooltipHeight);
                 tooltipVerticalMovement = '-10px';
                 backdrop.css({
                   bottom: 0,
                   left: 0,
                   borderRadius: '14px 14px 0 0',
                   transformOrigin: '50% 100%',
                   marginTop: tooltipHeight,
                   marginLeft: tooltipWidth / 2 - backdropOffsetWidth / 2
                 });
               }
               // Left Position
               else if (tooltipPosition === "left") {
                   targetTop = origin.offset().top + originHeight / 2 - tooltipHeight / 2;
                   targetLeft = origin.offset().left - tooltipWidth - margin;
                   newCoordinates = repositionWithinScreen(targetLeft, targetTop, tooltipWidth, tooltipHeight);
   
                   tooltipHorizontalMovement = '-10px';
                   backdrop.css({
                     top: '-7px',
                     right: 0,
                     width: '14px',
                     height: '14px',
                     borderRadius: '14px 0 0 14px',
                     transformOrigin: '95% 50%',
                     marginTop: tooltipHeight / 2,
                     marginLeft: tooltipWidth
                   });
                 }
                 // Right Position
                 else if (tooltipPosition === "right") {
                     targetTop = origin.offset().top + originHeight / 2 - tooltipHeight / 2;
                     targetLeft = origin.offset().left + originWidth + margin;
                     newCoordinates = repositionWithinScreen(targetLeft, targetTop, tooltipWidth, tooltipHeight);
   
                     tooltipHorizontalMovement = '+10px';
                     backdrop.css({
                       top: '-7px',
                       left: 0,
                       width: '14px',
                       height: '14px',
                       borderRadius: '0 14px 14px 0',
                       transformOrigin: '5% 50%',
                       marginTop: tooltipHeight / 2,
                       marginLeft: '0px'
                     });
                   } else {
                     // Bottom Position
                     targetTop = origin.offset().top + origin.outerHeight() + margin;
                     targetLeft = origin.offset().left + originWidth / 2 - tooltipWidth / 2;
                     newCoordinates = repositionWithinScreen(targetLeft, targetTop, tooltipWidth, tooltipHeight);
                     tooltipVerticalMovement = '+10px';
                     backdrop.css({
                       top: 0,
                       left: 0,
                       marginLeft: tooltipWidth / 2 - backdropOffsetWidth / 2
                     });
                   }
   
               // Set tooptip css placement
               tooltipEl.css({
                 top: newCoordinates.y,
                 left: newCoordinates.x
               });
   
               // Calculate Scale to fill
               scaleXFactor = Math.SQRT2 * tooltipWidth / parseInt(backdropOffsetWidth);
               scaleYFactor = Math.SQRT2 * tooltipHeight / parseInt(backdropOffsetHeight);
               scaleFactor = Math.max(scaleXFactor, scaleYFactor);
   
               tooltipEl.velocity({ translateY: tooltipVerticalMovement, translateX: tooltipHorizontalMovement }, { duration: 350, queue: false }).velocity({ opacity: 1 }, { duration: 300, delay: 50, queue: false });
               backdrop.css({ visibility: 'visible' }).velocity({ opacity: 1 }, { duration: 55, delay: 0, queue: false }).velocity({ scaleX: scaleFactor, scaleY: scaleFactor }, { duration: 300, delay: 0, queue: false, easing: 'easeInOutQuad' });
             };
   
             timeoutRef = setTimeout(showTooltip, tooltipDelay); // End Interval
   
             // Mouse Out
           },
           'mouseleave.tooltip': function () {
             // Reset State
             started = false;
             clearTimeout(timeoutRef);
   
             // Animate back
             setTimeout(function () {
               if (started !== true) {
                 tooltipEl.velocity({
                   opacity: 0, translateY: 0, translateX: 0 }, { duration: 225, queue: false });
                 backdrop.velocity({ opacity: 0, scaleX: 1, scaleY: 1 }, {
                   duration: 225,
                   queue: false,
                   complete: function () {
                     backdrop.css({ visibility: 'hidden' });
                     tooltipEl.css({ visibility: 'hidden' });
                     started = false;
                   }
                 });
               }
             }, 225);
           }
         });
       });
     };
   
     var repositionWithinScreen = function (x, y, width, height) {
       var newX = x;
       var newY = y;
   
       if (newX < 0) {
         newX = 4;
       } else if (newX + width > window.innerWidth) {
         newX -= newX + width - window.innerWidth;
       }
   
       if (newY < 0) {
         newY = 4;
       } else if (newY + height > window.innerHeight + $(window).scrollTop) {
         newY -= newY + height - window.innerHeight;
       }
   
       return { x: newX, y: newY };
     };
   
     $(document).ready(function () {
       $('.tooltipped').tooltip();
     });
   })(jQuery);
   ; /*!
     * Waves v0.6.4
     * http://fian.my.id/Waves
     *
     * Copyright 2014 Alfiana E. Sibuea and other contributors
     * Released under the MIT license
     * https://github.com/fians/Waves/blob/master/LICENSE
     */
   
   ;(function (window) {
     'use strict';
   
     var Waves = Waves || {};
     var $$ = document.querySelectorAll.bind(document);
   
     // Find exact position of element
     function isWindow(obj) {
       return obj !== null && obj === obj.window;
     }
   
     function getWindow(elem) {
       return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
     }
   
     function offset(elem) {
       var docElem,
           win,
           box = { top: 0, left: 0 },
           doc = elem && elem.ownerDocument;
   
       docElem = doc.documentElement;
   
       if (typeof elem.getBoundingClientRect !== typeof undefined) {
         box = elem.getBoundingClientRect();
       }
       win = getWindow(doc);
       return {
         top: box.top + win.pageYOffset - docElem.clientTop,
         left: box.left + win.pageXOffset - docElem.clientLeft
       };
     }
   
     function convertStyle(obj) {
       var style = '';
   
       for (var a in obj) {
         if (obj.hasOwnProperty(a)) {
           style += a + ':' + obj[a] + ';';
         }
       }
   
       return style;
     }
   
     var Effect = {
   
       // Effect delay
       duration: 750,
   
       show: function (e, element) {
   
         // Disable right click
         if (e.button === 2) {
           return false;
         }
   
         var el = element || this;
   
         // Create ripple
         var ripple = document.createElement('div');
         ripple.className = 'waves-ripple';
         el.appendChild(ripple);
   
         // Get click coordinate and element witdh
         var pos = offset(el);
         var relativeY = e.pageY - pos.top;
         var relativeX = e.pageX - pos.left;
         var scale = 'scale(' + el.clientWidth / 100 * 10 + ')';
   
         // Support for touch devices
         if ('touches' in e) {
           relativeY = e.touches[0].pageY - pos.top;
           relativeX = e.touches[0].pageX - pos.left;
         }
   
         // Attach data to element
         ripple.setAttribute('data-hold', Date.now());
         ripple.setAttribute('data-scale', scale);
         ripple.setAttribute('data-x', relativeX);
         ripple.setAttribute('data-y', relativeY);
   
         // Set ripple position
         var rippleStyle = {
           'top': relativeY + 'px',
           'left': relativeX + 'px'
         };
   
         ripple.className = ripple.className + ' waves-notransition';
         ripple.setAttribute('style', convertStyle(rippleStyle));
         ripple.className = ripple.className.replace('waves-notransition', '');
   
         // Scale the ripple
         rippleStyle['-webkit-transform'] = scale;
         rippleStyle['-moz-transform'] = scale;
         rippleStyle['-ms-transform'] = scale;
         rippleStyle['-o-transform'] = scale;
         rippleStyle.transform = scale;
         rippleStyle.opacity = '1';
   
         rippleStyle['-webkit-transition-duration'] = Effect.duration + 'ms';
         rippleStyle['-moz-transition-duration'] = Effect.duration + 'ms';
         rippleStyle['-o-transition-duration'] = Effect.duration + 'ms';
         rippleStyle['transition-duration'] = Effect.duration + 'ms';
   
         rippleStyle['-webkit-transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
         rippleStyle['-moz-transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
         rippleStyle['-o-transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
         rippleStyle['transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
   
         ripple.setAttribute('style', convertStyle(rippleStyle));
       },
   
       hide: function (e) {
         TouchHandler.touchup(e);
   
         var el = this;
         var width = el.clientWidth * 1.4;
   
         // Get first ripple
         var ripple = null;
         var ripples = el.getElementsByClassName('waves-ripple');
         if (ripples.length > 0) {
           ripple = ripples[ripples.length - 1];
         } else {
           return false;
         }
   
         var relativeX = ripple.getAttribute('data-x');
         var relativeY = ripple.getAttribute('data-y');
         var scale = ripple.getAttribute('data-scale');
   
         // Get delay beetween mousedown and mouse leave
         var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
         var delay = 350 - diff;
   
         if (delay < 0) {
           delay = 0;
         }
   
         // Fade out ripple after delay
         setTimeout(function () {
           var style = {
             'top': relativeY + 'px',
             'left': relativeX + 'px',
             'opacity': '0',
   
             // Duration
             '-webkit-transition-duration': Effect.duration + 'ms',
             '-moz-transition-duration': Effect.duration + 'ms',
             '-o-transition-duration': Effect.duration + 'ms',
             'transition-duration': Effect.duration + 'ms',
             '-webkit-transform': scale,
             '-moz-transform': scale,
             '-ms-transform': scale,
             '-o-transform': scale,
             'transform': scale
           };
   
           ripple.setAttribute('style', convertStyle(style));
   
           setTimeout(function () {
             try {
               el.removeChild(ripple);
             } catch (e) {
               return false;
             }
           }, Effect.duration);
         }, delay);
       },
   
       // Little hack to make <input> can perform waves effect
       wrapInput: function (elements) {
         for (var a = 0; a < elements.length; a++) {
           var el = elements[a];
   
           if (el.tagName.toLowerCase() === 'input') {
             var parent = el.parentNode;
   
             // If input already have parent just pass through
             if (parent.tagName.toLowerCase() === 'i' && parent.className.indexOf('waves-effect') !== -1) {
               continue;
             }
   
             // Put element class and style to the specified parent
             var wrapper = document.createElement('i');
             wrapper.className = el.className + ' waves-input-wrapper';
   
             var elementStyle = el.getAttribute('style');
   
             if (!elementStyle) {
               elementStyle = '';
             }
   
             wrapper.setAttribute('style', elementStyle);
   
             el.className = 'waves-button-input';
             el.removeAttribute('style');
   
             // Put element as child
             parent.replaceChild(wrapper, el);
             wrapper.appendChild(el);
           }
         }
       }
     };
   
     /**
      * Disable mousedown event for 500ms during and after touch
      */
     var TouchHandler = {
       /* uses an integer rather than bool so there's no issues with
        * needing to clear timeouts if another touch event occurred
        * within the 500ms. Cannot mouseup between touchstart and
        * touchend, nor in the 500ms after touchend. */
       touches: 0,
       allowEvent: function (e) {
         var allow = true;
   
         if (e.type === 'touchstart') {
           TouchHandler.touches += 1; //push
         } else if (e.type === 'touchend' || e.type === 'touchcancel') {
           setTimeout(function () {
             if (TouchHandler.touches > 0) {
               TouchHandler.touches -= 1; //pop after 500ms
             }
           }, 500);
         } else if (e.type === 'mousedown' && TouchHandler.touches > 0) {
           allow = false;
         }
   
         return allow;
       },
       touchup: function (e) {
         TouchHandler.allowEvent(e);
       }
     };
   
     /**
      * Delegated click handler for .waves-effect element.
      * returns null when .waves-effect element not in "click tree"
      */
     function getWavesEffectElement(e) {
       if (TouchHandler.allowEvent(e) === false) {
         return null;
       }
   
       var element = null;
       var target = e.target || e.srcElement;
   
       while (target.parentNode !== null) {
         if (!(target instanceof SVGElement) && target.className.indexOf('waves-effect') !== -1) {
           element = target;
           break;
         }
         target = target.parentNode;
       }
       return element;
     }
   
     /**
      * Bubble the click and show effect if .waves-effect elem was found
      */
     function showEffect(e) {
       var element = getWavesEffectElement(e);
   
       if (element !== null) {
         Effect.show(e, element);
   
         if ('ontouchstart' in window) {
           element.addEventListener('touchend', Effect.hide, false);
           element.addEventListener('touchcancel', Effect.hide, false);
         }
   
         element.addEventListener('mouseup', Effect.hide, false);
         element.addEventListener('mouseleave', Effect.hide, false);
         element.addEventListener('dragend', Effect.hide, false);
       }
     }
   
     Waves.displayEffect = function (options) {
       options = options || {};
   
       if ('duration' in options) {
         Effect.duration = options.duration;
       }
   
       //Wrap input inside <i> tag
       Effect.wrapInput($$('.waves-effect'));
   
       if ('ontouchstart' in window) {
         document.body.addEventListener('touchstart', showEffect, false);
       }
   
       document.body.addEventListener('mousedown', showEffect, false);
     };
   
     /**
      * Attach Waves to an input element (or any element which doesn't
      * bubble mouseup/mousedown events).
      *   Intended to be used with dynamically loaded forms/inputs, or
      * where the user doesn't want a delegated click handler.
      */
     Waves.attach = function (element) {
       //FUTURE: automatically add waves classes and allow users
       // to specify them with an options param? Eg. light/classic/button
       if (element.tagName.toLowerCase() === 'input') {
         Effect.wrapInput([element]);
         element = element.parentNode;
       }
   
       if ('ontouchstart' in window) {
         element.addEventListener('touchstart', showEffect, false);
       }
   
       element.addEventListener('mousedown', showEffect, false);
     };
   
     window.Waves = Waves;
   
     document.addEventListener('DOMContentLoaded', function () {
       Waves.displayEffect();
     }, false);
   })(window);
   ;(function ($) {
     'use strict';
   
     var _defaults = {
       displayLength: Infinity,
       inDuration: 300,
       outDuration: 375,
       className: undefined,
       completeCallback: undefined,
       activationPercent: 0.8
     };
   
     var Toast = function () {
       function Toast(message, displayLength, className, completeCallback) {
         _classCallCheck(this, Toast);
   
         if (!message) {
           return;
         }
   
         /**
          * Options for the toast
          * @member Toast#options
          */
         this.options = {
           displayLength: displayLength,
           className: className,
           completeCallback: completeCallback
         };
   
         this.options = $.extend({}, Toast.defaults, this.options);
         this.message = message;
   
         /**
          * Describes current pan state toast
          * @type {Boolean}
          */
         this.panning = false;
   
         /**
          * Time remaining until toast is removed
          */
         this.timeRemaining = this.options.displayLength;
   
         if (Toast._toasts.length === 0) {
           Toast._createContainer();
         }
   
         // Create new toast
         Toast._toasts.push(this);
         var toastElement = this.createToast();
         toastElement.M_Toast = this;
         this.el = toastElement;
         this._animateIn();
         this.setTimer();
       }
   
       _createClass(Toast, [{
         key: 'createToast',
   
   
         /**
          * Create toast and append it to toast container
          */
         value: function createToast() {
           var toast = document.createElement('div');
           toast.classList.add('toast');
   
           // Add custom classes onto toast
           if (this.options.className) {
             var classes = this.options.className.split(' ');
             var i = void 0,
                 count = void 0;
             for (i = 0, count = classes.length; i < count; i++) {
               toast.classList.add(classes[i]);
             }
           }
   
           // Set content
           if (typeof HTMLElement === 'object' ? this.message instanceof HTMLElement : this.message && typeof this.message === 'object' && this.message !== null && this.message.nodeType === 1 && typeof this.message.nodeName === 'string') {
             toast.appendChild(this.message);
   
             // Check if it is jQuery object
           } else if (this.message instanceof jQuery) {
             $(toast).append(this.message);
   
             // Insert as text;
           } else {
             toast.innerHTML = this.message;
           }
   
           // Append toasft
           Toast._container.appendChild(toast);
           return toast;
         }
   
         /**
          * Animate in toast
          */
   
       }, {
         key: '_animateIn',
         value: function _animateIn() {
           // Animate toast in
           Vel(this.el, { top: 0, opacity: 1 }, {
             duration: 300,
             easing: 'easeOutCubic',
             queue: false
           });
         }
   
         /**
          * Create setInterval which automatically removes toast when timeRemaining >= 0
          * has been reached
          */
   
       }, {
         key: 'setTimer',
         value: function setTimer() {
           var _this3 = this;
   
           if (this.timeRemaining !== Infinity) {
             this.counterInterval = setInterval(function () {
               // If toast is not being dragged, decrease its time remaining
               if (!_this3.panning) {
                 _this3.timeRemaining -= 20;
               }
   
               // Animate toast out
               if (_this3.timeRemaining <= 0) {
                 _this3.remove();
               }
             }, 20);
           }
         }
   
         /**
          * Dismiss toast with animation
          */
   
       }, {
         key: 'remove',
         value: function remove() {
           var _this4 = this;
   
           window.clearInterval(this.counterInterval);
           var activationDistance = this.el.offsetWidth * this.options.activationPercent;
   
           if (this.wasSwiped) {
             this.el.style.transition = 'transform .05s, opacity .05s';
             this.el.style.transform = 'translateX(' + activationDistance + 'px)';
             this.el.style.opacity = 0;
           }
   
           Vel(this.el, { opacity: 0, marginTop: '-40px' }, {
             duration: this.options.outDuration,
             easing: 'easeOutExpo',
             queue: false,
             complete: function () {
               // Call the optional callback
               if (typeof _this4.options.completeCallback === 'function') {
                 _this4.options.completeCallback();
               }
               // Remove toast from DOM
               _this4.el.parentNode.removeChild(_this4.el);
               Toast._toasts.splice(Toast._toasts.indexOf(_this4), 1);
               if (Toast._toasts.length === 0) {
                 Toast._removeContainer();
               }
             }
           });
         }
       }], [{
         key: '_createContainer',
   
   
         /**
          * Append toast container and add event handlers
          */
         value: function _createContainer() {
           var container = document.createElement('div');
           container.setAttribute('id', 'toast-container');
   
           // Add event handler
           container.addEventListener('touchstart', Toast._onDragStart);
           container.addEventListener('touchmove', Toast._onDragMove);
           container.addEventListener('touchend', Toast._onDragEnd);
   
           container.addEventListener('mousedown', Toast._onDragStart);
           document.addEventListener('mousemove', Toast._onDragMove);
           document.addEventListener('mouseup', Toast._onDragEnd);
   
           document.body.appendChild(container);
           Toast._container = container;
         }
   
         /**
          * Remove toast container and event handlers
          */
   
       }, {
         key: '_removeContainer',
         value: function _removeContainer() {
           // Add event handler
           document.removeEventListener('mousemove', Toast._onDragMove);
           document.removeEventListener('mouseup', Toast._onDragEnd);
   
           Toast._container.parentNode.removeChild(Toast._container);
           Toast._container = null;
         }
   
         /**
          * Begin drag handler
          * @param {Event} e
          */
   
       }, {
         key: '_onDragStart',
         value: function _onDragStart(e) {
           if (e.target && $(e.target).closest('.toast').length) {
             var $toast = $(e.target).closest('.toast');
             var toast = $toast[0].M_Toast;
             toast.panning = true;
             Toast._draggedToast = toast;
             toast.el.classList.add('panning');
             toast.el.style.transition = null;
             toast.startingXPos = Toast._xPos(e);
             toast.time = Date.now();
             toast.xPos = Toast._xPos(e);
           }
         }
   
         /**
          * Drag move handler
          * @param {Event} e
          */
   
       }, {
         key: '_onDragMove',
         value: function _onDragMove(e) {
           if (!!Toast._draggedToast) {
             e.preventDefault();
             var toast = Toast._draggedToast;
             toast.deltaX = Math.abs(toast.xPos - Toast._xPos(e));
             toast.xPos = Toast._xPos(e);
             toast.velocityX = toast.deltaX / (Date.now() - toast.time);
             toast.time = Date.now();
   
             var totalDeltaX = toast.xPos - toast.startingXPos;
             var activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
             toast.el.style.transform = 'translateX(' + totalDeltaX + 'px)';
             toast.el.style.opacity = 1 - Math.abs(totalDeltaX / activationDistance);
           }
         }
   
         /**
          * End drag handler
          * @param {Event} e
          */
   
       }, {
         key: '_onDragEnd',
         value: function _onDragEnd(e) {
           if (!!Toast._draggedToast) {
             var toast = Toast._draggedToast;
             toast.panning = false;
             toast.el.classList.remove('panning');
   
             var totalDeltaX = toast.xPos - toast.startingXPos;
             var activationDistance = toast.el.offsetWidth * toast.options.activationPercent;
             var shouldBeDismissed = Math.abs(totalDeltaX) > activationDistance || toast.velocityX > 1;
   
             // Remove toast
             if (shouldBeDismissed) {
               toast.wasSwiped = true;
               toast.remove();
   
               // Animate toast back to original position
             } else {
               toast.el.style.transition = 'transform .2s, opacity .2s';
               toast.el.style.transform = null;
               toast.el.style.opacity = null;
             }
             Toast._draggedToast = null;
           }
         }
   
         /**
          * Get x position of mouse or touch event
          * @param {Event} e
          */
   
       }, {
         key: '_xPos',
         value: function _xPos(e) {
           if (e.targetTouches && e.targetTouches.length >= 1) {
             return e.targetTouches[0].clientX;
           }
           // mouse event
           return e.clientX;
         }
   
         /**
          * Remove all toasts
          */
   
       }, {
         key: 'removeAll',
         value: function removeAll() {
           for (var toastIndex in Toast._toasts) {
             Toast._toasts[toastIndex].remove();
           }
         }
       }, {
         key: 'defaults',
         get: function () {
           return _defaults;
         }
       }]);
   
       return Toast;
     }();
   
     /**
      * @static
      * @memberof Toast
      * @type {Array.<Toast>}
      */
   
   
     Toast._toasts = [];
   
     /**
      * @static
      * @memberof Toast
      */
     Toast._container = null;
   
     /**
      * @static
      * @memberof Toast
      * @type {Toast}
      */
     Toast._draggedToast = null;
   
     window.Materialize.Toast = Toast;
     window.Materialize.toast = function (message, displayLength, className, completeCallback) {
       return new Toast(message, displayLength, className, completeCallback);
     };
   })(jQuery);
   ;(function ($) {
   
     var methods = {
       init: function (options) {
         var defaults = {
           menuWidth: 300,
           edge: 'left',
           closeOnClick: false,
           draggable: true,
           onOpen: null,
           onClose: null
         };
         options = $.extend(defaults, options);
   
         $(this).each(function () {
           var $this = $(this);
           var menuId = $this.attr('data-activates');
           var menu = $("#" + menuId);
   
           // Set to width
           if (options.menuWidth != 300) {
             menu.css('width', options.menuWidth);
           }
   
           // Add Touch Area
           var $dragTarget = $('.drag-target[data-sidenav="' + menuId + '"]');
           if (options.draggable) {
             // Regenerate dragTarget
             if ($dragTarget.length) {
               $dragTarget.remove();
             }
   
             $dragTarget = $('<div class="drag-target"></div>').attr('data-sidenav', menuId);
             $('body').append($dragTarget);
           } else {
             $dragTarget = $();
           }
   
           if (options.edge == 'left') {
             menu.css('transform', 'translateX(-100%)');
             $dragTarget.css({ 'left': 0 }); // Add Touch Area
           } else {
             menu.addClass('right-aligned') // Change text-alignment to right
             .css('transform', 'translateX(100%)');
             $dragTarget.css({ 'right': 0 }); // Add Touch Area
           }
   
           // If fixed sidenav, bring menu out
           if (menu.hasClass('fixed')) {
             if (window.innerWidth > 992) {
               menu.css('transform', 'translateX(0)');
             }
           }
   
           // Window resize to reset on large screens fixed
           if (menu.hasClass('fixed')) {
             $(window).resize(function () {
               if (window.innerWidth > 992) {
                 // Close menu if window is resized bigger than 992 and user has fixed sidenav
                 if ($('#sidenav-overlay').length !== 0 && menuOut) {
                   removeMenu(true);
                 } else {
                   // menu.removeAttr('style');
                   menu.css('transform', 'translateX(0%)');
                   // menu.css('width', options.menuWidth);
                 }
               } else if (menuOut === false) {
                 if (options.edge === 'left') {
                   menu.css('transform', 'translateX(-100%)');
                 } else {
                   menu.css('transform', 'translateX(100%)');
                 }
               }
             });
           }
   
           // if closeOnClick, then add close event for all a tags in side sideNav
           if (options.closeOnClick === true) {
             menu.on("click.itemclick", "a:not(.collapsible-header)", function () {
               if (!(window.innerWidth > 992 && menu.hasClass('fixed'))) {
                 removeMenu();
               }
             });
           }
   
           var removeMenu = function (restoreNav) {
             panning = false;
             menuOut = false;
             // Reenable scrolling
             $('body').css({
               overflow: '',
               width: ''
             });
   
             $('#sidenav-overlay').velocity({ opacity: 0 }, { duration: 200,
               queue: false, easing: 'easeOutQuad',
               complete: function () {
                 $(this).remove();
               } });
             if (options.edge === 'left') {
               // Reset phantom div
               $dragTarget.css({ width: '', right: '', left: '0' });
               menu.velocity({ 'translateX': '-100%' }, { duration: 200,
                 queue: false,
                 easing: 'easeOutCubic',
                 complete: function () {
                   if (restoreNav === true) {
                     // Restore Fixed sidenav
                     menu.removeAttr('style');
                     menu.css('width', options.menuWidth);
                   }
                 }
   
               });
             } else {
               // Reset phantom div
               $dragTarget.css({ width: '', right: '0', left: '' });
               menu.velocity({ 'translateX': '100%' }, { duration: 200,
                 queue: false,
                 easing: 'easeOutCubic',
                 complete: function () {
                   if (restoreNav === true) {
                     // Restore Fixed sidenav
                     menu.removeAttr('style');
                     menu.css('width', options.menuWidth);
                   }
                 }
               });
             }
   
             // Callback
             if (typeof options.onClose === 'function') {
               options.onClose.call(this, menu);
             }
           };
   
           // Touch Event
           var panning = false;
           var menuOut = false;
   
           if (options.draggable) {
             $dragTarget.on('click', function () {
               if (menuOut) {
                 removeMenu();
               }
             });
   
             $dragTarget.hammer({
               prevent_default: false
             }).on('pan', function (e) {
   
               if (e.gesture.pointerType == "touch") {
   
                 var direction = e.gesture.direction;
                 var x = e.gesture.center.x;
                 var y = e.gesture.center.y;
                 var velocityX = e.gesture.velocityX;
   
                 // Vertical scroll bugfix
                 if (x === 0 && y === 0) {
                   return;
                 }
   
                 // Disable Scrolling
                 var $body = $('body');
                 var $overlay = $('#sidenav-overlay');
                 var oldWidth = $body.innerWidth();
                 $body.css('overflow', 'hidden');
                 $body.width(oldWidth);
   
                 // If overlay does not exist, create one and if it is clicked, close menu
                 if ($overlay.length === 0) {
                   $overlay = $('<div id="sidenav-overlay"></div>');
                   $overlay.css('opacity', 0).click(function () {
                     removeMenu();
                   });
   
                   // Run 'onOpen' when sidenav is opened via touch/swipe if applicable
                   if (typeof options.onOpen === 'function') {
                     options.onOpen.call(this, menu);
                   }
   
                   $('body').append($overlay);
                 }
   
                 // Keep within boundaries
                 if (options.edge === 'left') {
                   if (x > options.menuWidth) {
                     x = options.menuWidth;
                   } else if (x < 0) {
                     x = 0;
                   }
                 }
   
                 if (options.edge === 'left') {
                   // Left Direction
                   if (x < options.menuWidth / 2) {
                     menuOut = false;
                   }
                   // Right Direction
                   else if (x >= options.menuWidth / 2) {
                       menuOut = true;
                     }
                   menu.css('transform', 'translateX(' + (x - options.menuWidth) + 'px)');
                 } else {
                   // Left Direction
                   if (x < window.innerWidth - options.menuWidth / 2) {
                     menuOut = true;
                   }
                   // Right Direction
                   else if (x >= window.innerWidth - options.menuWidth / 2) {
                       menuOut = false;
                     }
                   var rightPos = x - options.menuWidth / 2;
                   if (rightPos < 0) {
                     rightPos = 0;
                   }
   
                   menu.css('transform', 'translateX(' + rightPos + 'px)');
                 }
   
                 // Percentage overlay
                 var overlayPerc;
                 if (options.edge === 'left') {
                   overlayPerc = x / options.menuWidth;
                   $overlay.velocity({ opacity: overlayPerc }, { duration: 10, queue: false, easing: 'easeOutQuad' });
                 } else {
                   overlayPerc = Math.abs((x - window.innerWidth) / options.menuWidth);
                   $overlay.velocity({ opacity: overlayPerc }, { duration: 10, queue: false, easing: 'easeOutQuad' });
                 }
               }
             }).on('panend', function (e) {
   
               if (e.gesture.pointerType == "touch") {
                 var $overlay = $('#sidenav-overlay');
                 var velocityX = e.gesture.velocityX;
                 var x = e.gesture.center.x;
                 var leftPos = x - options.menuWidth;
                 var rightPos = x - options.menuWidth / 2;
                 if (leftPos > 0) {
                   leftPos = 0;
                 }
                 if (rightPos < 0) {
                   rightPos = 0;
                 }
                 panning = false;
   
                 if (options.edge === 'left') {
                   // If velocityX <= 0.3 then the user is flinging the menu closed so ignore menuOut
                   if (menuOut && velocityX <= 0.3 || velocityX < -0.5) {
                     // Return menu to open
                     if (leftPos !== 0) {
                       menu.velocity({ 'translateX': [0, leftPos] }, { duration: 300, queue: false, easing: 'easeOutQuad' });
                     }
   
                     $overlay.velocity({ opacity: 1 }, { duration: 50, queue: false, easing: 'easeOutQuad' });
                     $dragTarget.css({ width: '50%', right: 0, left: '' });
                     menuOut = true;
                   } else if (!menuOut || velocityX > 0.3) {
                     // Enable Scrolling
                     $('body').css({
                       overflow: '',
                       width: ''
                     });
                     // Slide menu closed
                     menu.velocity({ 'translateX': [-1 * options.menuWidth - 10, leftPos] }, { duration: 200, queue: false, easing: 'easeOutQuad' });
                     $overlay.velocity({ opacity: 0 }, { duration: 200, queue: false, easing: 'easeOutQuad',
                       complete: function () {
                         // Run 'onClose' when sidenav is closed via touch/swipe if applicable
                         if (typeof options.onClose === 'function') {
                           options.onClose.call(this, menu);
                         }
   
                         $(this).remove();
                       } });
                     $dragTarget.css({ width: '10px', right: '', left: 0 });
                   }
                 } else {
                   if (menuOut && velocityX >= -0.3 || velocityX > 0.5) {
                     // Return menu to open
                     if (rightPos !== 0) {
                       menu.velocity({ 'translateX': [0, rightPos] }, { duration: 300, queue: false, easing: 'easeOutQuad' });
                     }
   
                     $overlay.velocity({ opacity: 1 }, { duration: 50, queue: false, easing: 'easeOutQuad' });
                     $dragTarget.css({ width: '50%', right: '', left: 0 });
                     menuOut = true;
                   } else if (!menuOut || velocityX < -0.3) {
                     // Enable Scrolling
                     $('body').css({
                       overflow: '',
                       width: ''
                     });
   
                     // Slide menu closed
                     menu.velocity({ 'translateX': [options.menuWidth + 10, rightPos] }, { duration: 200, queue: false, easing: 'easeOutQuad' });
                     $overlay.velocity({ opacity: 0 }, { duration: 200, queue: false, easing: 'easeOutQuad',
                       complete: function () {
                         // Run 'onClose' when sidenav is closed via touch/swipe if applicable
                         if (typeof options.onClose === 'function') {
                           options.onClose.call(this, menu);
                         }
   
                         $(this).remove();
                       } });
                     $dragTarget.css({ width: '10px', right: 0, left: '' });
                   }
                 }
               }
             });
           }
   
           $this.off('click.sidenav').on('click.sidenav', function () {
             if (menuOut === true) {
               menuOut = false;
               panning = false;
               removeMenu();
             } else {
   
               // Disable Scrolling
               var $body = $('body');
               var $overlay = $('<div id="sidenav-overlay"></div>');
               var oldWidth = $body.innerWidth();
               $body.css('overflow', 'hidden');
               $body.width(oldWidth);
   
               // Push current drag target on top of DOM tree
               $('body').append($dragTarget);
   
               if (options.edge === 'left') {
                 $dragTarget.css({ width: '50%', right: 0, left: '' });
                 menu.velocity({ 'translateX': [0, -1 * options.menuWidth] }, { duration: 300, queue: false, easing: 'easeOutQuad' });
               } else {
                 $dragTarget.css({ width: '50%', right: '', left: 0 });
                 menu.velocity({ 'translateX': [0, options.menuWidth] }, { duration: 300, queue: false, easing: 'easeOutQuad' });
               }
   
               // Overlay close on click
               $overlay.css('opacity', 0).click(function () {
                 menuOut = false;
                 panning = false;
                 removeMenu();
                 $overlay.velocity({ opacity: 0 }, { duration: 300, queue: false, easing: 'easeOutQuad',
                   complete: function () {
                     $(this).remove();
                   }
                 });
               });
   
               // Append body
               $('body').append($overlay);
               $overlay.velocity({ opacity: 1 }, { duration: 300, queue: false, easing: 'easeOutQuad',
                 complete: function () {
                   menuOut = true;
                   panning = false;
                 }
               });
   
               // Callback
               if (typeof options.onOpen === 'function') {
                 options.onOpen.call(this, menu);
               }
             }
   
             return false;
           });
         });
       },
       destroy: function () {
         var $overlay = $('#sidenav-overlay');
         var $dragTarget = $('.drag-target[data-sidenav="' + $(this).attr('data-activates') + '"]');
         $overlay.trigger('click');
         $dragTarget.remove();
         $(this).off('click');
         $overlay.remove();
       },
       show: function () {
         this.trigger('click');
       },
       hide: function () {
         $('#sidenav-overlay').trigger('click');
       }
     };
   
     $.fn.sideNav = function (methodOrOptions) {
       if (methods[methodOrOptions]) {
         return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
       } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
         // Default to "init"
         return methods.init.apply(this, arguments);
       } else {
         $.error('Method ' + methodOrOptions + ' does not exist on jQuery.sideNav');
       }
     }; // Plugin end
   })(jQuery);
   ; /**
     * Extend jquery with a scrollspy plugin.
     * This watches the window scroll and fires events when elements are scrolled into viewport.
     *
     * throttle() and getTime() taken from Underscore.js
     * https://github.com/jashkenas/underscore
     *
     * @author Copyright 2013 John Smart
     * @license https://raw.github.com/thesmart/jquery-scrollspy/master/LICENSE
     * @see https://github.com/thesmart
     * @version 0.1.2
     */
   (function ($) {
   
     var jWindow = $(window);
     var elements = [];
     var elementsInView = [];
     var isSpying = false;
     var ticks = 0;
     var unique_id = 1;
     var offset = {
       top: 0,
       right: 0,
       bottom: 0,
       left: 0
   
       /**
        * Find elements that are within the boundary
        * @param {number} top
        * @param {number} right
        * @param {number} bottom
        * @param {number} left
        * @return {jQuery}		A collection of elements
        */
     };function findElements(top, right, bottom, left) {
       var hits = $();
       $.each(elements, function (i, element) {
         if (element.height() > 0) {
           var elTop = element.offset().top,
               elLeft = element.offset().left,
               elRight = elLeft + element.width(),
               elBottom = elTop + element.height();
   
           var isIntersect = !(elLeft > right || elRight < left || elTop > bottom || elBottom < top);
   
           if (isIntersect) {
             hits.push(element);
           }
         }
       });
   
       return hits;
     }
   
     /**
      * Called when the user scrolls the window
      */
     function onScroll(scrollOffset) {
       // unique tick id
       ++ticks;
   
       // viewport rectangle
       var top = jWindow.scrollTop(),
           left = jWindow.scrollLeft(),
           right = left + jWindow.width(),
           bottom = top + jWindow.height();
   
       // determine which elements are in view
       var intersections = findElements(top + offset.top + scrollOffset || 200, right + offset.right, bottom + offset.bottom, left + offset.left);
       $.each(intersections, function (i, element) {
   
         var lastTick = element.data('scrollSpy:ticks');
         if (typeof lastTick != 'number') {
           // entered into view
           element.triggerHandler('scrollSpy:enter');
         }
   
         // update tick id
         element.data('scrollSpy:ticks', ticks);
       });
   
       // determine which elements are no longer in view
       $.each(elementsInView, function (i, element) {
         var lastTick = element.data('scrollSpy:ticks');
         if (typeof lastTick == 'number' && lastTick !== ticks) {
           // exited from view
           element.triggerHandler('scrollSpy:exit');
           element.data('scrollSpy:ticks', null);
         }
       });
   
       // remember elements in view for next tick
       elementsInView = intersections;
     }
   
     /**
      * Called when window is resized
     */
     function onWinSize() {
       jWindow.trigger('scrollSpy:winSize');
     }
   
     /**
      * Enables ScrollSpy using a selector
      * @param {jQuery|string} selector  The elements collection, or a selector
      * @param {Object=} options	Optional.
            throttle : number -> scrollspy throttling. Default: 100 ms
            offsetTop : number -> offset from top. Default: 0
            offsetRight : number -> offset from right. Default: 0
            offsetBottom : number -> offset from bottom. Default: 0
            offsetLeft : number -> offset from left. Default: 0
                 activeClass : string -> Class name to be added to the active link. Default: active
      * @returns {jQuery}
      */
     $.scrollSpy = function (selector, options) {
       var defaults = {
         throttle: 100,
         scrollOffset: 200, // offset - 200 allows elements near bottom of page to scroll
         activeClass: 'active',
         getActiveElement: function (id) {
           return 'a[href="#' + id + '"]';
         }
       };
       options = $.extend(defaults, options);
   
       var visible = [];
       selector = $(selector);
       selector.each(function (i, element) {
         elements.push($(element));
         $(element).data("scrollSpy:id", i);
         // Smooth scroll to section
         $('a[href="#' + $(element).attr('id') + '"]').click(function (e) {
           e.preventDefault();
           var offset = $(Materialize.escapeHash(this.hash)).offset().top + 1;
           $('html, body').animate({ scrollTop: offset - options.scrollOffset }, { duration: 400, queue: false, easing: 'easeOutCubic' });
         });
       });
   
       offset.top = options.offsetTop || 0;
       offset.right = options.offsetRight || 0;
       offset.bottom = options.offsetBottom || 0;
       offset.left = options.offsetLeft || 0;
   
       var throttledScroll = Materialize.throttle(function () {
         onScroll(options.scrollOffset);
       }, options.throttle || 100);
       var readyScroll = function () {
         $(document).ready(throttledScroll);
       };
   
       if (!isSpying) {
         jWindow.on('scroll', readyScroll);
         jWindow.on('resize', readyScroll);
         isSpying = true;
       }
   
       // perform a scan once, after current execution context, and after dom is ready
       setTimeout(readyScroll, 0);
   
       selector.on('scrollSpy:enter', function () {
         visible = $.grep(visible, function (value) {
           return value.height() != 0;
         });
   
         var $this = $(this);
   
         if (visible[0]) {
           $(options.getActiveElement(visible[0].attr('id'))).removeClass(options.activeClass);
           if ($this.data('scrollSpy:id') < visible[0].data('scrollSpy:id')) {
             visible.unshift($(this));
           } else {
             visible.push($(this));
           }
         } else {
           visible.push($(this));
         }
   
         $(options.getActiveElement(visible[0].attr('id'))).addClass(options.activeClass);
       });
       selector.on('scrollSpy:exit', function () {
         visible = $.grep(visible, function (value) {
           return value.height() != 0;
         });
   
         if (visible[0]) {
           $(options.getActiveElement(visible[0].attr('id'))).removeClass(options.activeClass);
           var $this = $(this);
           visible = $.grep(visible, function (value) {
             return value.attr('id') != $this.attr('id');
           });
           if (visible[0]) {
             // Check if empty
             $(options.getActiveElement(visible[0].attr('id'))).addClass(options.activeClass);
           }
         }
       });
   
       return selector;
     };
   
     /**
      * Listen for window resize events
      * @param {Object=} options						Optional. Set { throttle: number } to change throttling. Default: 100 ms
      * @returns {jQuery}		$(window)
      */
     $.winSizeSpy = function (options) {
       $.winSizeSpy = function () {
         return jWindow;
       }; // lock from multiple calls
       options = options || {
         throttle: 100
       };
       return jWindow.on('resize', Materialize.throttle(onWinSize, options.throttle || 100));
     };
   
     /**
      * Enables ScrollSpy on a collection of elements
      * e.g. $('.scrollSpy').scrollSpy()
      * @param {Object=} options	Optional.
                                             throttle : number -> scrollspy throttling. Default: 100 ms
                                             offsetTop : number -> offset from top. Default: 0
                                             offsetRight : number -> offset from right. Default: 0
                                             offsetBottom : number -> offset from bottom. Default: 0
                                             offsetLeft : number -> offset from left. Default: 0
      * @returns {jQuery}
      */
     $.fn.scrollSpy = function (options) {
       return $.scrollSpy($(this), options);
     };
   })(jQuery);
   ;(function ($) {
     $(document).ready(function () {
   
       // Function to update labels of text fields
       Materialize.updateTextFields = function () {
         var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
         $(input_selector).each(function (index, element) {
           var $this = $(this);
           if ($(element).val().length > 0 || $(element).is(':focus') || element.autofocus || $this.attr('placeholder') !== undefined) {
             $this.siblings('label').addClass('active');
           } else if ($(element)[0].validity) {
             $this.siblings('label').toggleClass('active', $(element)[0].validity.badInput === true);
           } else {
             $this.siblings('label').removeClass('active');
           }
         });
       };
   
       // Text based inputs
       var input_selector = 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
   
       // Add active if form auto complete
       $(document).on('change', input_selector, function () {
         if ($(this).val().length !== 0 || $(this).attr('placeholder') !== undefined) {
           $(this).siblings('label').addClass('active');
         }
         validate_field($(this));
       });
   
       // Add active if input element has been pre-populated on document ready
       $(document).ready(function () {
         Materialize.updateTextFields();
       });
   
       // HTML DOM FORM RESET handling
       $(document).on('reset', function (e) {
         var formReset = $(e.target);
         if (formReset.is('form')) {
           formReset.find(input_selector).removeClass('valid').removeClass('invalid');
           formReset.find(input_selector).each(function () {
             if ($(this).attr('value') === '') {
               $(this).siblings('label').removeClass('active');
             }
           });
   
           // Reset select
           formReset.find('select.initialized').each(function () {
             var reset_text = formReset.find('option[selected]').text();
             formReset.siblings('input.select-dropdown').val(reset_text);
           });
         }
       });
   
       // Add active when element has focus
       $(document).on('focus', input_selector, function () {
         $(this).siblings('label, .prefix').addClass('active');
       });
   
       $(document).on('blur', input_selector, function () {
         var $inputElement = $(this);
         var selector = ".prefix";
   
         if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') === undefined) {
           selector += ", label";
         }
   
         $inputElement.siblings(selector).removeClass('active');
   
         validate_field($inputElement);
       });
   
       window.validate_field = function (object) {
         var hasLength = object.attr('data-length') !== undefined;
         var lenAttr = parseInt(object.attr('data-length'));
         var len = object.val().length;
   
         if (object.val().length === 0 && object[0].validity.badInput === false && !object.is(':required')) {
           if (object.hasClass('validate')) {
             object.removeClass('valid');
             object.removeClass('invalid');
           }
         } else {
           if (object.hasClass('validate')) {
             // Check for character counter attributes
             if (object.is(':valid') && hasLength && len <= lenAttr || object.is(':valid') && !hasLength) {
               object.removeClass('invalid');
               object.addClass('valid');
             } else {
               object.removeClass('valid');
               object.addClass('invalid');
             }
           }
         }
       };
   
       // Radio and Checkbox focus class
       var radio_checkbox = 'input[type=radio], input[type=checkbox]';
       $(document).on('keyup.radio', radio_checkbox, function (e) {
         // TAB, check if tabbing to radio or checkbox.
         if (e.which === 9) {
           $(this).addClass('tabbed');
           var $this = $(this);
           $this.one('blur', function (e) {
   
             $(this).removeClass('tabbed');
           });
           return;
         }
       });
   
       // Textarea Auto Resize
       var hiddenDiv = $('.hiddendiv').first();
       if (!hiddenDiv.length) {
         hiddenDiv = $('<div class="hiddendiv common"></div>');
         $('body').append(hiddenDiv);
       }
       var text_area_selector = '.materialize-textarea';
   
       function textareaAutoResize($textarea) {
         // Set font properties of hiddenDiv
   
         var fontFamily = $textarea.css('font-family');
         var fontSize = $textarea.css('font-size');
         var lineHeight = $textarea.css('line-height');
         var padding = $textarea.css('padding');
   
         if (fontSize) {
           hiddenDiv.css('font-size', fontSize);
         }
         if (fontFamily) {
           hiddenDiv.css('font-family', fontFamily);
         }
         if (lineHeight) {
           hiddenDiv.css('line-height', lineHeight);
         }
         if (padding) {
           hiddenDiv.css('padding', padding);
         }
   
         // Set original-height, if none
         if (!$textarea.data('original-height')) {
           $textarea.data('original-height', $textarea.height());
         }
   
         if ($textarea.attr('wrap') === 'off') {
           hiddenDiv.css('overflow-wrap', 'normal').css('white-space', 'pre');
         }
   
         hiddenDiv.text($textarea.val() + '\n');
         var content = hiddenDiv.html().replace(/\n/g, '<br>');
         hiddenDiv.html(content);
   
         // When textarea is hidden, width goes crazy.
         // Approximate with half of window size
   
         if ($textarea.is(':visible')) {
           hiddenDiv.css('width', $textarea.width());
         } else {
           hiddenDiv.css('width', $(window).width() / 2);
         }
   
         /**
          * Resize if the new height is greater than the
          * original height of the textarea
          */
         if ($textarea.data('original-height') <= hiddenDiv.height()) {
           $textarea.css('height', hiddenDiv.height());
         } else if ($textarea.val().length < $textarea.data('previous-length')) {
           /**
            * In case the new height is less than original height, it
            * means the textarea has less text than before
            * So we set the height to the original one
            */
           $textarea.css('height', $textarea.data('original-height'));
         }
         $textarea.data('previous-length', $textarea.val().length);
       }
   
       $(text_area_selector).each(function () {
         var $textarea = $(this);
         /**
          * Instead of resizing textarea on document load,
          * store the original height and the original length
          */
         $textarea.data('original-height', $textarea.height());
         $textarea.data('previous-length', $textarea.val().length);
       });
   
       $('body').on('keyup keydown autoresize', text_area_selector, function () {
         textareaAutoResize($(this));
       });
   
       // File Input Path
       $(document).on('change', '.file-field input[type="file"]', function () {
         var file_field = $(this).closest('.file-field');
         var path_input = file_field.find('input.file-path');
         var files = $(this)[0].files;
         var file_names = [];
         for (var i = 0; i < files.length; i++) {
           file_names.push(files[i].name);
         }
         path_input.val(file_names.join(", "));
         path_input.trigger('change');
       });
   
       /****************
       *  Range Input  *
       ****************/
   
       var range_type = 'input[type=range]';
       var range_mousedown = false;
       var left;
   
       $(range_type).each(function () {
         var thumb = $('<span class="thumb"><span class="value"></span></span>');
         $(this).after(thumb);
       });
   
       var showRangeBubble = function (thumb) {
         var paddingLeft = parseInt(thumb.parent().css('padding-left'));
         var marginLeft = -7 + paddingLeft + 'px';
         thumb.velocity({ height: "30px", width: "30px", top: "-30px", marginLeft: marginLeft }, { duration: 300, easing: 'easeOutExpo' });
       };
   
       var calcRangeOffset = function (range) {
         var width = range.width() - 15;
         var max = parseFloat(range.attr('max'));
         var min = parseFloat(range.attr('min'));
         var percent = (parseFloat(range.val()) - min) / (max - min);
         return percent * width;
       };
   
       var range_wrapper = '.range-field';
       $(document).on('change', range_type, function (e) {
         var thumb = $(this).siblings('.thumb');
         thumb.find('.value').html($(this).val());
   
         if (!thumb.hasClass('active')) {
           showRangeBubble(thumb);
         }
   
         var offsetLeft = calcRangeOffset($(this));
         thumb.addClass('active').css('left', offsetLeft);
       });
   
       $(document).on('mousedown touchstart', range_type, function (e) {
         var thumb = $(this).siblings('.thumb');
   
         // If thumb indicator does not exist yet, create it
         if (thumb.length <= 0) {
           thumb = $('<span class="thumb"><span class="value"></span></span>');
           $(this).after(thumb);
         }
   
         // Set indicator value
         thumb.find('.value').html($(this).val());
   
         range_mousedown = true;
         $(this).addClass('active');
   
         if (!thumb.hasClass('active')) {
           showRangeBubble(thumb);
         }
   
         if (e.type !== 'input') {
           var offsetLeft = calcRangeOffset($(this));
           thumb.addClass('active').css('left', offsetLeft);
         }
       });
   
       $(document).on('mouseup touchend', range_wrapper, function () {
         range_mousedown = false;
         $(this).removeClass('active');
       });
   
       $(document).on('input mousemove touchmove', range_wrapper, function (e) {
         var thumb = $(this).children('.thumb');
         var left;
         var input = $(this).find(range_type);
   
         if (range_mousedown) {
           if (!thumb.hasClass('active')) {
             showRangeBubble(thumb);
           }
   
           var offsetLeft = calcRangeOffset(input);
           thumb.addClass('active').css('left', offsetLeft);
           thumb.find('.value').html(thumb.siblings(range_type).val());
         }
       });
   
       $(document).on('mouseout touchleave', range_wrapper, function () {
         if (!range_mousedown) {
   
           var thumb = $(this).children('.thumb');
           var paddingLeft = parseInt($(this).css('padding-left'));
           var marginLeft = 7 + paddingLeft + 'px';
   
           if (thumb.hasClass('active')) {
             thumb.velocity({ height: '0', width: '0', top: '10px', marginLeft: marginLeft }, { duration: 100 });
           }
           thumb.removeClass('active');
         }
       });
   
       /**************************
        * Auto complete plugin  *
        *************************/
       $.fn.autocomplete = function (options) {
         // Defaults
         var defaults = {
           data: {},
           limit: Infinity,
           onAutocomplete: null,
           minLength: 1
         };
   
         options = $.extend(defaults, options);
   
         return this.each(function () {
           var $input = $(this);
           var data = options.data,
               count = 0,
               activeIndex = -1,
               oldVal,
               $inputDiv = $input.closest('.input-field'); // Div to append on
   
           // Check if data isn't empty
           if (!$.isEmptyObject(data)) {
             var $autocomplete = $('<ul class="autocomplete-content dropdown-content"></ul>');
             var $oldAutocomplete;
   
             // Append autocomplete element.
             // Prevent double structure init.
             if ($inputDiv.length) {
               $oldAutocomplete = $inputDiv.children('.autocomplete-content.dropdown-content').first();
               if (!$oldAutocomplete.length) {
                 $inputDiv.append($autocomplete); // Set ul in body
               }
             } else {
               $oldAutocomplete = $input.next('.autocomplete-content.dropdown-content');
               if (!$oldAutocomplete.length) {
                 $input.after($autocomplete);
               }
             }
             if ($oldAutocomplete.length) {
               $autocomplete = $oldAutocomplete;
             }
   
             // Highlight partial match.
             var highlight = function (string, $el) {
               var img = $el.find('img');
               var matchStart = $el.text().toLowerCase().indexOf("" + string.toLowerCase() + ""),
                   matchEnd = matchStart + string.length - 1,
                   beforeMatch = $el.text().slice(0, matchStart),
                   matchText = $el.text().slice(matchStart, matchEnd + 1),
                   afterMatch = $el.text().slice(matchEnd + 1);
               $el.html("<span>" + beforeMatch + "<span class='highlight'>" + matchText + "</span>" + afterMatch + "</span>");
               if (img.length) {
                 $el.prepend(img);
               }
             };
   
             // Reset current element position
             var resetCurrentElement = function () {
               activeIndex = -1;
               $autocomplete.find('.active').removeClass('active');
             };
   
             // Remove autocomplete elements
             var removeAutocomplete = function () {
               $autocomplete.empty();
               resetCurrentElement();
               oldVal = undefined;
             };
   
             $input.off('blur.autocomplete').on('blur.autocomplete', function () {
               removeAutocomplete();
             });
   
             // Perform search
             $input.off('keyup.autocomplete focus.autocomplete').on('keyup.autocomplete focus.autocomplete', function (e) {
               // Reset count.
               count = 0;
               var val = $input.val().toLowerCase();
   
               // Don't capture enter or arrow key usage.
               if (e.which === 13 || e.which === 38 || e.which === 40) {
                 return;
               }
   
               // Check if the input isn't empty
               if (oldVal !== val) {
                 removeAutocomplete();
   
                 if (val.length >= options.minLength) {
                   for (var key in data) {
                     if (data.hasOwnProperty(key) && key.toLowerCase().indexOf(val) !== -1) {
                       // Break if past limit
                       if (count >= options.limit) {
                         break;
                       }
   
                       var autocompleteOption = $('<li></li>');
                       if (!!data[key]) {
                         autocompleteOption.append('<img src="' + data[key] + '" class="right circle"><span>' + key + '</span>');
                       } else {
                         autocompleteOption.append('<span>' + key + '</span>');
                       }
   
                       $autocomplete.append(autocompleteOption);
                       highlight(val, autocompleteOption);
                       count++;
                     }
                   }
                 }
               }
   
               // Update oldVal
               oldVal = val;
             });
   
             $input.off('keydown.autocomplete').on('keydown.autocomplete', function (e) {
               // Arrow keys and enter key usage
               var keyCode = e.which,
                   liElement,
                   numItems = $autocomplete.children('li').length,
                   $active = $autocomplete.children('.active').first();
   
               // select element on Enter
               if (keyCode === 13 && activeIndex >= 0) {
                 liElement = $autocomplete.children('li').eq(activeIndex);
                 if (liElement.length) {
                   liElement.trigger('mousedown.autocomplete');
                   e.preventDefault();
                 }
                 return;
               }
   
               // Capture up and down key
               if (keyCode === 38 || keyCode === 40) {
                 e.preventDefault();
   
                 if (keyCode === 38 && activeIndex > 0) {
                   activeIndex--;
                 }
   
                 if (keyCode === 40 && activeIndex < numItems - 1) {
                   activeIndex++;
                 }
   
                 $active.removeClass('active');
                 if (activeIndex >= 0) {
                   $autocomplete.children('li').eq(activeIndex).addClass('active');
                 }
               }
             });
   
             // Set input value
             $autocomplete.off('mousedown.autocomplete touchstart.autocomplete').on('mousedown.autocomplete touchstart.autocomplete', 'li', function () {
               var text = $(this).text().trim();
               $input.val(text);
               $input.trigger('change');
               removeAutocomplete();
   
               // Handle onAutocomplete callback.
               if (typeof options.onAutocomplete === "function") {
                 options.onAutocomplete.call(this, text);
               }
             });
   
             // Empty data
           } else {
             $input.off('keyup.autocomplete focus.autocomplete');
           }
         });
       };
     }); // End of $(document).ready
   
     /*******************
      *  Select Plugin  *
      ******************/
     $.fn.material_select = function (callback) {
       $(this).each(function () {
         var $select = $(this);
   
         if ($select.hasClass('browser-default')) {
           return; // Continue to next (return false breaks out of entire loop)
         }
   
         var multiple = $select.attr('multiple') ? true : false,
             lastID = $select.attr('data-select-id'); // Tear down structure if Select needs to be rebuilt
   
         if (lastID) {
           $select.parent().find('span.caret').remove();
           $select.parent().find('input').remove();
   
           $select.unwrap();
           $('ul#select-options-' + lastID).remove();
         }
   
         // If destroying the select, remove the selelct-id and reset it to it's uninitialized state.
         if (callback === 'destroy') {
           $select.removeAttr('data-select-id').removeClass('initialized');
           $(window).off('click.select');
           return;
         }
   
         var uniqueID = Materialize.guid();
         $select.attr('data-select-id', uniqueID);
         var wrapper = $('<div class="select-wrapper"></div>');
         wrapper.addClass($select.attr('class'));
         if ($select.is(':disabled')) wrapper.addClass('disabled');
         var options = $('<ul id="select-options-' + uniqueID + '" class="dropdown-content select-dropdown ' + (multiple ? 'multiple-select-dropdown' : '') + '"></ul>'),
             selectChildren = $select.children('option, optgroup'),
             valuesSelected = [],
             optionsHover = false;
   
         var label = $select.find('option:selected').html() || $select.find('option:first').html() || "";
   
         // Function that renders and appends the option taking into
         // account type and possible image icon.
         var appendOptionWithIcon = function (select, option, type) {
           // Add disabled attr if disabled
           var disabledClass = option.is(':disabled') ? 'disabled ' : '';
           var optgroupClass = type === 'optgroup-option' ? 'optgroup-option ' : '';
           var multipleCheckbox = multiple ? '<input type="checkbox"' + disabledClass + '/><label></label>' : '';
   
           // add icons
           var icon_url = option.data('icon');
           var classes = option.attr('class');
           if (!!icon_url) {
             var classString = '';
             if (!!classes) classString = ' class="' + classes + '"';
   
             // Check for multiple type.
             options.append($('<li class="' + disabledClass + optgroupClass + '"><img alt="" src="' + icon_url + '"' + classString + '><span>' + multipleCheckbox + option.html() + '</span></li>'));
             return true;
           }
   
           // Check for multiple type.
           options.append($('<li class="' + disabledClass + optgroupClass + '"><span>' + multipleCheckbox + option.html() + '</span></li>'));
         };
   
         /* Create dropdown structure. */
         if (selectChildren.length) {
           selectChildren.each(function () {
             if ($(this).is('option')) {
               // Direct descendant option.
               if (multiple) {
                 appendOptionWithIcon($select, $(this), 'multiple');
               } else {
                 appendOptionWithIcon($select, $(this));
               }
             } else if ($(this).is('optgroup')) {
               // Optgroup.
               var selectOptions = $(this).children('option');
               options.append($('<li class="optgroup"><span>' + $(this).attr('label') + '</span></li>'));
   
               selectOptions.each(function () {
                 appendOptionWithIcon($select, $(this), 'optgroup-option');
               });
             }
           });
         }
   
         options.find('li:not(.optgroup)').each(function (i) {
           $(this).click(function (e) {
             // Check if option element is disabled
             if (!$(this).hasClass('disabled') && !$(this).hasClass('optgroup')) {
               var selected = true;
   
               if (multiple) {
                 $('input[type="checkbox"]', this).prop('checked', function (i, v) {
                   return !v;
                 });
                 selected = toggleEntryFromArray(valuesSelected, i, $select);
                 $newSelect.trigger('focus');
               } else {
                 options.find('li').removeClass('active');
                 $(this).toggleClass('active');
                 $newSelect.val($(this).text());
               }
   
               activateOption(options, $(this));
               $select.find('option').eq(i).prop('selected', selected);
               // Trigger onchange() event
               $select.trigger('change');
               if (typeof callback !== 'undefined') callback();
             }
   
             e.stopPropagation();
           });
         });
   
         // Wrap Elements
         $select.wrap(wrapper);
         // Add Select Display Element
         var dropdownIcon = $('<span class="caret">&#9660;</span>');
   
         // escape double quotes
         var sanitizedLabelHtml = label.replace(/"/g, '&quot;');
   
         var $newSelect = $('<input type="text" class="select-dropdown" readonly="true" ' + ($select.is(':disabled') ? 'disabled' : '') + ' data-activates="select-options-' + uniqueID + '" value="' + sanitizedLabelHtml + '"/>');
         $select.before($newSelect);
         $newSelect.before(dropdownIcon);
   
         $newSelect.after(options);
         // Check if section element is disabled
         if (!$select.is(':disabled')) {
           $newSelect.dropdown({ 'hover': false });
         }
   
         // Copy tabindex
         if ($select.attr('tabindex')) {
           $($newSelect[0]).attr('tabindex', $select.attr('tabindex'));
         }
   
         $select.addClass('initialized');
   
         $newSelect.on({
           'focus': function () {
             if ($('ul.select-dropdown').not(options[0]).is(':visible')) {
               $('input.select-dropdown').trigger('close');
               $(window).off('click.select');
             }
             if (!options.is(':visible')) {
               $(this).trigger('open', ['focus']);
               var label = $(this).val();
               if (multiple && label.indexOf(',') >= 0) {
                 label = label.split(',')[0];
               }
   
               var selectedOption = options.find('li').filter(function () {
                 return $(this).text().toLowerCase() === label.toLowerCase();
               })[0];
               activateOption(options, selectedOption, true);
   
               $(window).off('click.select').on('click.select', function () {
                 multiple && (optionsHover || $newSelect.trigger('close'));
                 $(window).off('click.select');
               });
             }
           },
           'click': function (e) {
             e.stopPropagation();
           }
         });
   
         $newSelect.on('blur', function () {
           if (!multiple) {
             $(this).trigger('close');
             $(window).off('click.select');
           }
           options.find('li.selected').removeClass('selected');
         });
   
         options.hover(function () {
           optionsHover = true;
         }, function () {
           optionsHover = false;
         });
   
         // Add initial multiple selections.
         if (multiple) {
           $select.find("option:selected:not(:disabled)").each(function () {
             var index = $(this).index();
   
             toggleEntryFromArray(valuesSelected, index, $select);
             options.find("li").eq(index).find(":checkbox").prop("checked", true);
           });
         }
   
         /**
          * Make option as selected and scroll to selected position
          * @param {jQuery} collection  Select options jQuery element
          * @param {Element} newOption  element of the new option
          * @param {Boolean} firstActivation  If on first activation of select
          */
         var activateOption = function (collection, newOption, firstActivation) {
           if (newOption) {
             collection.find('li.selected').removeClass('selected');
             var option = $(newOption);
             option.addClass('selected');
             if (!multiple || !!firstActivation) {
               options.scrollTo(option);
             }
           }
         };
   
         // Allow user to search by typing
         // this array is cleared after 1 second
         var filterQuery = [],
             onKeyDown = function (e) {
           // TAB - switch to another input
           if (e.which == 9) {
             $newSelect.trigger('close');
             return;
           }
   
           // ARROW DOWN WHEN SELECT IS CLOSED - open select options
           if (e.which == 40 && !options.is(':visible')) {
             $newSelect.trigger('open');
             return;
           }
   
           // ENTER WHEN SELECT IS CLOSED - submit form
           if (e.which == 13 && !options.is(':visible')) {
             return;
           }
   
           e.preventDefault();
   
           // CASE WHEN USER TYPE LETTERS
           var letter = String.fromCharCode(e.which).toLowerCase(),
               nonLetters = [9, 13, 27, 38, 40];
           if (letter && nonLetters.indexOf(e.which) === -1) {
             filterQuery.push(letter);
   
             var string = filterQuery.join(''),
                 newOption = options.find('li').filter(function () {
               return $(this).text().toLowerCase().indexOf(string) === 0;
             })[0];
   
             if (newOption) {
               activateOption(options, newOption);
             }
           }
   
           // ENTER - select option and close when select options are opened
           if (e.which == 13) {
             var activeOption = options.find('li.selected:not(.disabled)')[0];
             if (activeOption) {
               $(activeOption).trigger('click');
               if (!multiple) {
                 $newSelect.trigger('close');
               }
             }
           }
   
           // ARROW DOWN - move to next not disabled option
           if (e.which == 40) {
             if (options.find('li.selected').length) {
               newOption = options.find('li.selected').next('li:not(.disabled)')[0];
             } else {
               newOption = options.find('li:not(.disabled)')[0];
             }
             activateOption(options, newOption);
           }
   
           // ESC - close options
           if (e.which == 27) {
             $newSelect.trigger('close');
           }
   
           // ARROW UP - move to previous not disabled option
           if (e.which == 38) {
             newOption = options.find('li.selected').prev('li:not(.disabled)')[0];
             if (newOption) activateOption(options, newOption);
           }
   
           // Automaticaly clean filter query so user can search again by starting letters
           setTimeout(function () {
             filterQuery = [];
           }, 1000);
         };
   
         $newSelect.on('keydown', onKeyDown);
       });
   
       function toggleEntryFromArray(entriesArray, entryIndex, select) {
         var index = entriesArray.indexOf(entryIndex),
             notAdded = index === -1;
   
         if (notAdded) {
           entriesArray.push(entryIndex);
         } else {
           entriesArray.splice(index, 1);
         }
   
         select.siblings('ul.dropdown-content').find('li:not(.optgroup)').eq(entryIndex).toggleClass('active');
   
         // use notAdded instead of true (to detect if the option is selected or not)
         select.find('option').eq(entryIndex).prop('selected', notAdded);
         setValueToInput(entriesArray, select);
   
         return notAdded;
       }
   
       function setValueToInput(entriesArray, select) {
         var value = '';
   
         for (var i = 0, count = entriesArray.length; i < count; i++) {
           var text = select.find('option').eq(entriesArray[i]).text();
   
           i === 0 ? value += text : value += ', ' + text;
         }
   
         if (value === '') {
           value = select.find('option:disabled').eq(0).text();
         }
   
         select.siblings('input.select-dropdown').val(value);
       }
     };
   })(jQuery);
   ;(function ($) {
   
     var methods = {
   
       init: function (options) {
         var defaults = {
           indicators: true,
           height: 400,
           transition: 500,
           interval: 6000
         };
         options = $.extend(defaults, options);
   
         return this.each(function () {
   
           // For each slider, we want to keep track of
           // which slide is active and its associated content
           var $this = $(this);
           var $slider = $this.find('ul.slides').first();
           var $slides = $slider.find('> li');
           var $active_index = $slider.find('.active').index();
           var $active, $indicators, $interval;
           if ($active_index != -1) {
             $active = $slides.eq($active_index);
           }
   
           // Transitions the caption depending on alignment
           function captionTransition(caption, duration) {
             if (caption.hasClass("center-align")) {
               caption.velocity({ opacity: 0, translateY: -100 }, { duration: duration, queue: false });
             } else if (caption.hasClass("right-align")) {
               caption.velocity({ opacity: 0, translateX: 100 }, { duration: duration, queue: false });
             } else if (caption.hasClass("left-align")) {
               caption.velocity({ opacity: 0, translateX: -100 }, { duration: duration, queue: false });
             }
           }
   
           // This function will transition the slide to any index of the next slide
           function moveToSlide(index) {
             // Wrap around indices.
             if (index >= $slides.length) index = 0;else if (index < 0) index = $slides.length - 1;
   
             $active_index = $slider.find('.active').index();
   
             // Only do if index changes
             if ($active_index != index) {
               $active = $slides.eq($active_index);
               $caption = $active.find('.caption');
   
               $active.removeClass('active');
               $active.velocity({ opacity: 0 }, { duration: options.transition, queue: false, easing: 'easeOutQuad',
                 complete: function () {
                   $slides.not('.active').velocity({ opacity: 0, translateX: 0, translateY: 0 }, { duration: 0, queue: false });
                 } });
               captionTransition($caption, options.transition);
   
               // Update indicators
               if (options.indicators) {
                 $indicators.eq($active_index).removeClass('active');
               }
   
               $slides.eq(index).velocity({ opacity: 1 }, { duration: options.transition, queue: false, easing: 'easeOutQuad' });
               $slides.eq(index).find('.caption').velocity({ opacity: 1, translateX: 0, translateY: 0 }, { duration: options.transition, delay: options.transition, queue: false, easing: 'easeOutQuad' });
               $slides.eq(index).addClass('active');
   
               // Update indicators
               if (options.indicators) {
                 $indicators.eq(index).addClass('active');
               }
             }
           }
   
           // Set height of slider
           // If fullscreen, do nothing
           if (!$this.hasClass('fullscreen')) {
             if (options.indicators) {
               // Add height if indicators are present
               $this.height(options.height + 40);
             } else {
               $this.height(options.height);
             }
             $slider.height(options.height);
           }
   
           // Set initial positions of captions
           $slides.find('.caption').each(function () {
             captionTransition($(this), 0);
           });
   
           // Move img src into background-image
           $slides.find('img').each(function () {
             var placeholderBase64 = 'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
             if ($(this).attr('src') !== placeholderBase64) {
               $(this).css('background-image', 'url("' + $(this).attr('src') + '")');
               $(this).attr('src', placeholderBase64);
             }
           });
   
           // dynamically add indicators
           if (options.indicators) {
             $indicators = $('<ul class="indicators"></ul>');
             $slides.each(function (index) {
               var $indicator = $('<li class="indicator-item"></li>');
   
               // Handle clicks on indicators
               $indicator.click(function () {
                 var $parent = $slider.parent();
                 var curr_index = $parent.find($(this)).index();
                 moveToSlide(curr_index);
   
                 // reset interval
                 clearInterval($interval);
                 $interval = setInterval(function () {
                   $active_index = $slider.find('.active').index();
                   if ($slides.length == $active_index + 1) $active_index = 0; // loop to start
                   else $active_index += 1;
   
                   moveToSlide($active_index);
                 }, options.transition + options.interval);
               });
               $indicators.append($indicator);
             });
             $this.append($indicators);
             $indicators = $this.find('ul.indicators').find('li.indicator-item');
           }
   
           if ($active) {
             $active.show();
           } else {
             $slides.first().addClass('active').velocity({ opacity: 1 }, { duration: options.transition, queue: false, easing: 'easeOutQuad' });
   
             $active_index = 0;
             $active = $slides.eq($active_index);
   
             // Update indicators
             if (options.indicators) {
               $indicators.eq($active_index).addClass('active');
             }
           }
   
           // Adjust height to current slide
           $active.find('img').each(function () {
             $active.find('.caption').velocity({ opacity: 1, translateX: 0, translateY: 0 }, { duration: options.transition, queue: false, easing: 'easeOutQuad' });
           });
   
           // auto scroll
           $interval = setInterval(function () {
             $active_index = $slider.find('.active').index();
             moveToSlide($active_index + 1);
           }, options.transition + options.interval);
   
           // HammerJS, Swipe navigation
   
           // Touch Event
           var panning = false;
           var swipeLeft = false;
           var swipeRight = false;
   
           $this.hammer({
             prevent_default: false
           }).on('pan', function (e) {
             if (e.gesture.pointerType === "touch") {
   
               // reset interval
               clearInterval($interval);
   
               var direction = e.gesture.direction;
               var x = e.gesture.deltaX;
               var velocityX = e.gesture.velocityX;
               var velocityY = e.gesture.velocityY;
   
               $curr_slide = $slider.find('.active');
               if (Math.abs(velocityX) > Math.abs(velocityY)) {
                 $curr_slide.velocity({ translateX: x
                 }, { duration: 50, queue: false, easing: 'easeOutQuad' });
               }
   
               // Swipe Left
               if (direction === 4 && (x > $this.innerWidth() / 2 || velocityX < -0.65)) {
                 swipeRight = true;
               }
               // Swipe Right
               else if (direction === 2 && (x < -1 * $this.innerWidth() / 2 || velocityX > 0.65)) {
                   swipeLeft = true;
                 }
   
               // Make Slide Behind active slide visible
               var next_slide;
               if (swipeLeft) {
                 next_slide = $curr_slide.next();
                 if (next_slide.length === 0) {
                   next_slide = $slides.first();
                 }
                 next_slide.velocity({ opacity: 1
                 }, { duration: 300, queue: false, easing: 'easeOutQuad' });
               }
               if (swipeRight) {
                 next_slide = $curr_slide.prev();
                 if (next_slide.length === 0) {
                   next_slide = $slides.last();
                 }
                 next_slide.velocity({ opacity: 1
                 }, { duration: 300, queue: false, easing: 'easeOutQuad' });
               }
             }
           }).on('panend', function (e) {
             if (e.gesture.pointerType === "touch") {
   
               $curr_slide = $slider.find('.active');
               panning = false;
               curr_index = $slider.find('.active').index();
   
               if (!swipeRight && !swipeLeft || $slides.length <= 1) {
                 // Return to original spot
                 $curr_slide.velocity({ translateX: 0
                 }, { duration: 300, queue: false, easing: 'easeOutQuad' });
               } else if (swipeLeft) {
                 moveToSlide(curr_index + 1);
                 $curr_slide.velocity({ translateX: -1 * $this.innerWidth() }, { duration: 300, queue: false, easing: 'easeOutQuad',
                   complete: function () {
                     $curr_slide.velocity({ opacity: 0, translateX: 0 }, { duration: 0, queue: false });
                   } });
               } else if (swipeRight) {
                 moveToSlide(curr_index - 1);
                 $curr_slide.velocity({ translateX: $this.innerWidth() }, { duration: 300, queue: false, easing: 'easeOutQuad',
                   complete: function () {
                     $curr_slide.velocity({ opacity: 0, translateX: 0 }, { duration: 0, queue: false });
                   } });
               }
               swipeLeft = false;
               swipeRight = false;
   
               // Restart interval
               clearInterval($interval);
               $interval = setInterval(function () {
                 $active_index = $slider.find('.active').index();
                 if ($slides.length == $active_index + 1) $active_index = 0; // loop to start
                 else $active_index += 1;
   
                 moveToSlide($active_index);
               }, options.transition + options.interval);
             }
           });
   
           $this.on('sliderPause', function () {
             clearInterval($interval);
           });
   
           $this.on('sliderStart', function () {
             clearInterval($interval);
             $interval = setInterval(function () {
               $active_index = $slider.find('.active').index();
               if ($slides.length == $active_index + 1) $active_index = 0; // loop to start
               else $active_index += 1;
   
               moveToSlide($active_index);
             }, options.transition + options.interval);
           });
   
           $this.on('sliderNext', function () {
             $active_index = $slider.find('.active').index();
             moveToSlide($active_index + 1);
           });
   
           $this.on('sliderPrev', function () {
             $active_index = $slider.find('.active').index();
             moveToSlide($active_index - 1);
           });
         });
       },
       pause: function () {
         $(this).trigger('sliderPause');
       },
       start: function () {
         $(this).trigger('sliderStart');
       },
       next: function () {
         $(this).trigger('sliderNext');
       },
       prev: function () {
         $(this).trigger('sliderPrev');
       }
     };
   
     $.fn.slider = function (methodOrOptions) {
       if (methods[methodOrOptions]) {
         return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
       } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
         // Default to "init"
         return methods.init.apply(this, arguments);
       } else {
         $.error('Method ' + methodOrOptions + ' does not exist on jQuery.tooltip');
       }
     }; // Plugin end
   })(jQuery);
   ;(function ($) {
     $(document).ready(function () {
   
       $(document).on('click.card', '.card', function (e) {
         if ($(this).find('> .card-reveal').length) {
           var $card = $(e.target).closest('.card');
           if ($card.data('initialOverflow') === undefined) {
             $card.data('initialOverflow', $card.css('overflow') === undefined ? '' : $card.css('overflow'));
           }
           if ($(e.target).is($('.card-reveal .card-title')) || $(e.target).is($('.card-reveal .card-title i'))) {
             // Make Reveal animate down and display none
             $(this).find('.card-reveal').velocity({ translateY: 0 }, {
               duration: 225,
               queue: false,
               easing: 'easeInOutQuad',
               complete: function () {
                 $(this).css({ display: 'none' });
                 $card.css('overflow', $card.data('initialOverflow'));
               }
             });
           } else if ($(e.target).is($('.card .activator')) || $(e.target).is($('.card .activator i'))) {
             $card.css('overflow', 'hidden');
             $(this).find('.card-reveal').css({ display: 'block' }).velocity("stop", false).velocity({ translateY: '-100%' }, { duration: 300, queue: false, easing: 'easeInOutQuad' });
           }
         }
       });
     });
   })(jQuery);
   ;(function ($) {
     var materialChipsDefaults = {
       data: [],
       placeholder: '',
       secondaryPlaceholder: '',
       autocompleteOptions: {}
     };
   
     $(document).ready(function () {
       // Handle removal of static chips.
       $(document).on('click', '.chip .close', function (e) {
         var $chips = $(this).closest('.chips');
         if ($chips.attr('data-initialized')) {
           return;
         }
         $(this).closest('.chip').remove();
       });
     });
   
     $.fn.material_chip = function (options) {
       var self = this;
       this.$el = $(this);
       this.$document = $(document);
       this.SELS = {
         CHIPS: '.chips',
         CHIP: '.chip',
         INPUT: 'input',
         DELETE: '.material-icons',
         SELECTED_CHIP: '.selected'
       };
   
       if ('data' === options) {
         return this.$el.data('chips');
       }
   
       var curr_options = $.extend({}, materialChipsDefaults, options);
       self.hasAutocomplete = !$.isEmptyObject(curr_options.autocompleteOptions.data);
   
       // Initialize
       this.init = function () {
         var i = 0;
         var chips;
         self.$el.each(function () {
           var $chips = $(this);
           var chipId = Materialize.guid();
           self.chipId = chipId;
   
           if (!curr_options.data || !(curr_options.data instanceof Array)) {
             curr_options.data = [];
           }
           $chips.data('chips', curr_options.data);
           $chips.attr('data-index', i);
           $chips.attr('data-initialized', true);
   
           if (!$chips.hasClass(self.SELS.CHIPS)) {
             $chips.addClass('chips');
           }
   
           self.chips($chips, chipId);
           i++;
         });
       };
   
       this.handleEvents = function () {
         var SELS = self.SELS;
   
         self.$document.off('click.chips-focus', SELS.CHIPS).on('click.chips-focus', SELS.CHIPS, function (e) {
           $(e.target).find(SELS.INPUT).focus();
         });
   
         self.$document.off('click.chips-select', SELS.CHIP).on('click.chips-select', SELS.CHIP, function (e) {
           var $chip = $(e.target);
           if ($chip.length) {
             var wasSelected = $chip.hasClass('selected');
             var $chips = $chip.closest(SELS.CHIPS);
             $(SELS.CHIP).removeClass('selected');
   
             if (!wasSelected) {
               self.selectChip($chip.index(), $chips);
             }
           }
         });
   
         self.$document.off('keydown.chips').on('keydown.chips', function (e) {
           if ($(e.target).is('input, textarea')) {
             return;
           }
   
           // delete
           var $chip = self.$document.find(SELS.CHIP + SELS.SELECTED_CHIP);
           var $chips = $chip.closest(SELS.CHIPS);
           var length = $chip.siblings(SELS.CHIP).length;
           var index;
   
           if (!$chip.length) {
             return;
           }
   
           if (e.which === 8 || e.which === 46) {
             e.preventDefault();
   
             index = $chip.index();
             self.deleteChip(index, $chips);
   
             var selectIndex = null;
             if (index + 1 < length) {
               selectIndex = index;
             } else if (index === length || index + 1 === length) {
               selectIndex = length - 1;
             }
   
             if (selectIndex < 0) selectIndex = null;
   
             if (null !== selectIndex) {
               self.selectChip(selectIndex, $chips);
             }
             if (!length) $chips.find('input').focus();
   
             // left
           } else if (e.which === 37) {
             index = $chip.index() - 1;
             if (index < 0) {
               return;
             }
             $(SELS.CHIP).removeClass('selected');
             self.selectChip(index, $chips);
   
             // right
           } else if (e.which === 39) {
             index = $chip.index() + 1;
             $(SELS.CHIP).removeClass('selected');
             if (index > length) {
               $chips.find('input').focus();
               return;
             }
             self.selectChip(index, $chips);
           }
         });
   
         self.$document.off('focusin.chips', SELS.CHIPS + ' ' + SELS.INPUT).on('focusin.chips', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
           var $currChips = $(e.target).closest(SELS.CHIPS);
           $currChips.addClass('focus');
           $currChips.siblings('label, .prefix').addClass('active');
           $(SELS.CHIP).removeClass('selected');
         });
   
         self.$document.off('focusout.chips', SELS.CHIPS + ' ' + SELS.INPUT).on('focusout.chips', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
           var $currChips = $(e.target).closest(SELS.CHIPS);
           $currChips.removeClass('focus');
   
           // Remove active if empty
           if ($currChips.data('chips') === undefined || !$currChips.data('chips').length) {
             $currChips.siblings('label').removeClass('active');
           }
           $currChips.siblings('.prefix').removeClass('active');
         });
   
         self.$document.off('keydown.chips-add', SELS.CHIPS + ' ' + SELS.INPUT).on('keydown.chips-add', SELS.CHIPS + ' ' + SELS.INPUT, function (e) {
           var $target = $(e.target);
           var $chips = $target.closest(SELS.CHIPS);
           var chipsLength = $chips.children(SELS.CHIP).length;
   
           // enter
           if (13 === e.which) {
             // Override enter if autocompleting.
             if (self.hasAutocomplete && $chips.find('.autocomplete-content.dropdown-content').length && $chips.find('.autocomplete-content.dropdown-content').children().length) {
               return;
             }
   
             e.preventDefault();
             self.addChip({ tag: $target.val() }, $chips);
             $target.val('');
             return;
           }
   
           // delete or left
           if ((8 === e.keyCode || 37 === e.keyCode) && '' === $target.val() && chipsLength) {
             e.preventDefault();
             self.selectChip(chipsLength - 1, $chips);
             $target.blur();
             return;
           }
         });
   
         // Click on delete icon in chip.
         self.$document.off('click.chips-delete', SELS.CHIPS + ' ' + SELS.DELETE).on('click.chips-delete', SELS.CHIPS + ' ' + SELS.DELETE, function (e) {
           var $target = $(e.target);
           var $chips = $target.closest(SELS.CHIPS);
           var $chip = $target.closest(SELS.CHIP);
           e.stopPropagation();
           self.deleteChip($chip.index(), $chips);
           $chips.find('input').focus();
         });
       };
   
       this.chips = function ($chips, chipId) {
         $chips.empty();
         $chips.data('chips').forEach(function (elem) {
           $chips.append(self.renderChip(elem));
         });
         $chips.append($('<input id="' + chipId + '" class="input" placeholder="">'));
         self.setPlaceholder($chips);
   
         // Set for attribute for label
         var label = $chips.next('label');
         if (label.length) {
           label.attr('for', chipId);
   
           if ($chips.data('chips') !== undefined && $chips.data('chips').length) {
             label.addClass('active');
           }
         }
   
         // Setup autocomplete if needed.
         var input = $('#' + chipId);
         if (self.hasAutocomplete) {
           curr_options.autocompleteOptions.onAutocomplete = function (val) {
             self.addChip({ tag: val }, $chips);
             input.val('');
             input.focus();
           };
           input.autocomplete(curr_options.autocompleteOptions);
         }
       };
   
       /**
        * Render chip jQuery element.
        * @param {Object} elem
        * @return {jQuery}
        */
       this.renderChip = function (elem) {
         if (!elem.tag) return;
   
         var $renderedChip = $('<div class="chip"></div>');
         $renderedChip.text(elem.tag);
         if (elem.image) {
           $renderedChip.prepend($('<img />').attr('src', elem.image));
         }
         $renderedChip.append($('<i class="material-icons close">close</i>'));
         return $renderedChip;
       };
   
       this.setPlaceholder = function ($chips) {
         if ($chips.data('chips') !== undefined && !$chips.data('chips').length && curr_options.placeholder) {
           $chips.find('input').prop('placeholder', curr_options.placeholder);
         } else if (($chips.data('chips') === undefined || !!$chips.data('chips').length) && curr_options.secondaryPlaceholder) {
           $chips.find('input').prop('placeholder', curr_options.secondaryPlaceholder);
         }
       };
   
       this.isValid = function ($chips, elem) {
         var chips = $chips.data('chips');
         var exists = false;
         for (var i = 0; i < chips.length; i++) {
           if (chips[i].tag === elem.tag) {
             exists = true;
             return;
           }
         }
         return '' !== elem.tag && !exists;
       };
   
       this.addChip = function (elem, $chips) {
         if (!self.isValid($chips, elem)) {
           return;
         }
         var $renderedChip = self.renderChip(elem);
         var newData = [];
         var oldData = $chips.data('chips');
         for (var i = 0; i < oldData.length; i++) {
           newData.push(oldData[i]);
         }
         newData.push(elem);
   
         $chips.data('chips', newData);
         $renderedChip.insertBefore($chips.find('input'));
         $chips.trigger('chip.add', elem);
         self.setPlaceholder($chips);
       };
   
       this.deleteChip = function (chipIndex, $chips) {
         var chip = $chips.data('chips')[chipIndex];
         $chips.find('.chip').eq(chipIndex).remove();
   
         var newData = [];
         var oldData = $chips.data('chips');
         for (var i = 0; i < oldData.length; i++) {
           if (i !== chipIndex) {
             newData.push(oldData[i]);
           }
         }
   
         $chips.data('chips', newData);
         $chips.trigger('chip.delete', chip);
         self.setPlaceholder($chips);
       };
   
       this.selectChip = function (chipIndex, $chips) {
         var $chip = $chips.find('.chip').eq(chipIndex);
         if ($chip && false === $chip.hasClass('selected')) {
           $chip.addClass('selected');
           $chips.trigger('chip.select', $chips.data('chips')[chipIndex]);
         }
       };
   
       this.getChipsElement = function (index, $chips) {
         return $chips.eq(index);
       };
   
       // init
       this.init();
   
       this.handleEvents();
     };
   })(jQuery);
   ;(function ($) {
     $.fn.pushpin = function (options) {
       // Defaults
       var defaults = {
         top: 0,
         bottom: Infinity,
         offset: 0
       };
   
       // Remove pushpin event and classes
       if (options === "remove") {
         this.each(function () {
           if (id = $(this).data('pushpin-id')) {
             $(window).off('scroll.' + id);
             $(this).removeData('pushpin-id').removeClass('pin-top pinned pin-bottom').removeAttr('style');
           }
         });
         return false;
       }
   
       options = $.extend(defaults, options);
   
       $index = 0;
       return this.each(function () {
         var $uniqueId = Materialize.guid(),
             $this = $(this),
             $original_offset = $(this).offset().top;
   
         function removePinClasses(object) {
           object.removeClass('pin-top');
           object.removeClass('pinned');
           object.removeClass('pin-bottom');
         }
   
         function updateElements(objects, scrolled) {
           objects.each(function () {
             // Add position fixed (because its between top and bottom)
             if (options.top <= scrolled && options.bottom >= scrolled && !$(this).hasClass('pinned')) {
               removePinClasses($(this));
               $(this).css('top', options.offset);
               $(this).addClass('pinned');
             }
   
             // Add pin-top (when scrolled position is above top)
             if (scrolled < options.top && !$(this).hasClass('pin-top')) {
               removePinClasses($(this));
               $(this).css('top', 0);
               $(this).addClass('pin-top');
             }
   
             // Add pin-bottom (when scrolled position is below bottom)
             if (scrolled > options.bottom && !$(this).hasClass('pin-bottom')) {
               removePinClasses($(this));
               $(this).addClass('pin-bottom');
               $(this).css('top', options.bottom - $original_offset);
             }
           });
         }
   
         $(this).data('pushpin-id', $uniqueId);
         updateElements($this, $(window).scrollTop());
         $(window).on('scroll.' + $uniqueId, function () {
           var $scrolled = $(window).scrollTop() + options.offset;
           updateElements($this, $scrolled);
         });
       });
     };
   })(jQuery);;(function ($) {
     $(document).ready(function () {
   
       // jQuery reverse
       $.fn.reverse = [].reverse;
   
       // Hover behaviour: make sure this doesn't work on .click-to-toggle FABs!
       $(document).on('mouseenter.fixedActionBtn', '.fixed-action-btn:not(.click-to-toggle):not(.toolbar)', function (e) {
         var $this = $(this);
         openFABMenu($this);
       });
       $(document).on('mouseleave.fixedActionBtn', '.fixed-action-btn:not(.click-to-toggle):not(.toolbar)', function (e) {
         var $this = $(this);
         closeFABMenu($this);
       });
   
       // Toggle-on-click behaviour.
       $(document).on('click.fabClickToggle', '.fixed-action-btn.click-to-toggle > a', function (e) {
         var $this = $(this);
         var $menu = $this.parent();
         if ($menu.hasClass('active')) {
           closeFABMenu($menu);
         } else {
           openFABMenu($menu);
         }
       });
   
       // Toolbar transition behaviour.
       $(document).on('click.fabToolbar', '.fixed-action-btn.toolbar > a', function (e) {
         var $this = $(this);
         var $menu = $this.parent();
         FABtoToolbar($menu);
       });
     });
   
     $.fn.extend({
       openFAB: function () {
         openFABMenu($(this));
       },
       closeFAB: function () {
         closeFABMenu($(this));
       },
       openToolbar: function () {
         FABtoToolbar($(this));
       },
       closeToolbar: function () {
         toolbarToFAB($(this));
       }
     });
   
     var openFABMenu = function (btn) {
       var $this = btn;
       if ($this.hasClass('active') === false) {
   
         // Get direction option
         var horizontal = $this.hasClass('horizontal');
         var offsetY, offsetX;
   
         if (horizontal === true) {
           offsetX = 40;
         } else {
           offsetY = 40;
         }
   
         $this.addClass('active');
         $this.find('ul .btn-floating').velocity({ scaleY: ".4", scaleX: ".4", translateY: offsetY + 'px', translateX: offsetX + 'px' }, { duration: 0 });
   
         var time = 0;
         $this.find('ul .btn-floating').reverse().each(function () {
           $(this).velocity({ opacity: "1", scaleX: "1", scaleY: "1", translateY: "0", translateX: '0' }, { duration: 80, delay: time });
           time += 40;
         });
       }
     };
   
     var closeFABMenu = function (btn) {
       var $this = btn;
       // Get direction option
       var horizontal = $this.hasClass('horizontal');
       var offsetY, offsetX;
   
       if (horizontal === true) {
         offsetX = 40;
       } else {
         offsetY = 40;
       }
   
       $this.removeClass('active');
       var time = 0;
       $this.find('ul .btn-floating').velocity("stop", true);
       $this.find('ul .btn-floating').velocity({ opacity: "0", scaleX: ".4", scaleY: ".4", translateY: offsetY + 'px', translateX: offsetX + 'px' }, { duration: 80 });
     };
   
     /**
      * Transform FAB into toolbar
      * @param  {Object}  object jQuery object
      */
     var FABtoToolbar = function (btn) {
       if (btn.attr('data-open') === "true") {
         return;
       }
   
       var offsetX, offsetY, scaleFactor;
       var windowWidth = window.innerWidth;
       var windowHeight = window.innerHeight;
       var btnRect = btn[0].getBoundingClientRect();
       var anchor = btn.find('> a').first();
       var menu = btn.find('> ul').first();
       var backdrop = $('<div class="fab-backdrop"></div>');
       var fabColor = anchor.css('background-color');
       anchor.append(backdrop);
   
       offsetX = btnRect.left - windowWidth / 2 + btnRect.width / 2;
       offsetY = windowHeight - btnRect.bottom;
       scaleFactor = windowWidth / backdrop.width();
       btn.attr('data-origin-bottom', btnRect.bottom);
       btn.attr('data-origin-left', btnRect.left);
       btn.attr('data-origin-width', btnRect.width);
   
       // Set initial state
       btn.addClass('active');
       btn.attr('data-open', true);
       btn.css({
         'text-align': 'center',
         width: '100%',
         bottom: 0,
         left: 0,
         transform: 'translateX(' + offsetX + 'px)',
         transition: 'none'
       });
       anchor.css({
         transform: 'translateY(' + -offsetY + 'px)',
         transition: 'none'
       });
       backdrop.css({
         'background-color': fabColor
       });
   
       setTimeout(function () {
         btn.css({
           transform: '',
           transition: 'transform .2s cubic-bezier(0.550, 0.085, 0.680, 0.530), background-color 0s linear .2s'
         });
         anchor.css({
           overflow: 'visible',
           transform: '',
           transition: 'transform .2s'
         });
   
         setTimeout(function () {
           btn.css({
             overflow: 'hidden',
             'background-color': fabColor
           });
           backdrop.css({
             transform: 'scale(' + scaleFactor + ')',
             transition: 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)'
           });
           menu.find('> li > a').css({
             opacity: 1
           });
   
           // Scroll to close.
           $(window).on('scroll.fabToolbarClose', function () {
             toolbarToFAB(btn);
             $(window).off('scroll.fabToolbarClose');
             $(document).off('click.fabToolbarClose');
           });
   
           $(document).on('click.fabToolbarClose', function (e) {
             if (!$(e.target).closest(menu).length) {
               toolbarToFAB(btn);
               $(window).off('scroll.fabToolbarClose');
               $(document).off('click.fabToolbarClose');
             }
           });
         }, 100);
       }, 0);
     };
   
     /**
      * Transform toolbar back into FAB
      * @param  {Object}  object jQuery object
      */
     var toolbarToFAB = function (btn) {
       if (btn.attr('data-open') !== "true") {
         return;
       }
   
       var offsetX, offsetY, scaleFactor;
       var windowWidth = window.innerWidth;
       var windowHeight = window.innerHeight;
       var btnWidth = btn.attr('data-origin-width');
       var btnBottom = btn.attr('data-origin-bottom');
       var btnLeft = btn.attr('data-origin-left');
       var anchor = btn.find('> .btn-floating').first();
       var menu = btn.find('> ul').first();
       var backdrop = btn.find('.fab-backdrop');
       var fabColor = anchor.css('background-color');
   
       offsetX = btnLeft - windowWidth / 2 + btnWidth / 2;
       offsetY = windowHeight - btnBottom;
       scaleFactor = windowWidth / backdrop.width();
   
       // Hide backdrop
       btn.removeClass('active');
       btn.attr('data-open', false);
       btn.css({
         'background-color': 'transparent',
         transition: 'none'
       });
       anchor.css({
         transition: 'none'
       });
       backdrop.css({
         transform: 'scale(0)',
         'background-color': fabColor
       });
       menu.find('> li > a').css({
         opacity: ''
       });
   
       setTimeout(function () {
         backdrop.remove();
   
         // Set initial state.
         btn.css({
           'text-align': '',
           width: '',
           bottom: '',
           left: '',
           overflow: '',
           'background-color': '',
           transform: 'translate3d(' + -offsetX + 'px,0,0)'
         });
         anchor.css({
           overflow: '',
           transform: 'translate3d(0,' + offsetY + 'px,0)'
         });
   
         setTimeout(function () {
           btn.css({
             transform: 'translate3d(0,0,0)',
             transition: 'transform .2s'
           });
           anchor.css({
             transform: 'translate3d(0,0,0)',
             transition: 'transform .2s cubic-bezier(0.550, 0.055, 0.675, 0.190)'
           });
         }, 20);
       }, 200);
     };
   })(jQuery);
   ;(function ($) {
     // Image transition function
     Materialize.fadeInImage = function (selectorOrEl) {
       var element;
       if (typeof selectorOrEl === 'string') {
         element = $(selectorOrEl);
       } else if (typeof selectorOrEl === 'object') {
         element = selectorOrEl;
       } else {
         return;
       }
       element.css({ opacity: 0 });
       $(element).velocity({ opacity: 1 }, {
         duration: 650,
         queue: false,
         easing: 'easeOutSine'
       });
       $(element).velocity({ opacity: 1 }, {
         duration: 1300,
         queue: false,
         easing: 'swing',
         step: function (now, fx) {
           fx.start = 100;
           var grayscale_setting = now / 100;
           var brightness_setting = 150 - (100 - now) / 1.75;
   
           if (brightness_setting < 100) {
             brightness_setting = 100;
           }
           if (now >= 0) {
             $(this).css({
               "-webkit-filter": "grayscale(" + grayscale_setting + ")" + "brightness(" + brightness_setting + "%)",
               "filter": "grayscale(" + grayscale_setting + ")" + "brightness(" + brightness_setting + "%)"
             });
           }
         }
       });
     };
   
     // Horizontal staggered list
     Materialize.showStaggeredList = function (selectorOrEl) {
       var element;
       if (typeof selectorOrEl === 'string') {
         element = $(selectorOrEl);
       } else if (typeof selectorOrEl === 'object') {
         element = selectorOrEl;
       } else {
         return;
       }
       var time = 0;
       element.find('li').velocity({ translateX: "-100px" }, { duration: 0 });
   
       element.find('li').each(function () {
         $(this).velocity({ opacity: "1", translateX: "0" }, { duration: 800, delay: time, easing: [60, 10] });
         time += 120;
       });
     };
   
     $(document).ready(function () {
       // Hardcoded .staggered-list scrollFire
       // var staggeredListOptions = [];
       // $('ul.staggered-list').each(function (i) {
   
       //   var label = 'scrollFire-' + i;
       //   $(this).addClass(label);
       //   staggeredListOptions.push(
       //     {selector: 'ul.staggered-list.' + label,
       //      offset: 200,
       //      callback: 'showStaggeredList("ul.staggered-list.' + label + '")'});
       // });
       // scrollFire(staggeredListOptions);
   
       // HammerJS, Swipe navigation
   
       // Touch Event
       var swipeLeft = false;
       var swipeRight = false;
   
       // Dismissible Collections
       $('.dismissable').each(function () {
         $(this).hammer({
           prevent_default: false
         }).on('pan', function (e) {
           if (e.gesture.pointerType === "touch") {
             var $this = $(this);
             var direction = e.gesture.direction;
             var x = e.gesture.deltaX;
             var velocityX = e.gesture.velocityX;
   
             $this.velocity({ translateX: x
             }, { duration: 50, queue: false, easing: 'easeOutQuad' });
   
             // Swipe Left
             if (direction === 4 && (x > $this.innerWidth() / 2 || velocityX < -0.75)) {
               swipeLeft = true;
             }
   
             // Swipe Right
             if (direction === 2 && (x < -1 * $this.innerWidth() / 2 || velocityX > 0.75)) {
               swipeRight = true;
             }
           }
         }).on('panend', function (e) {
           // Reset if collection is moved back into original position
           if (Math.abs(e.gesture.deltaX) < $(this).innerWidth() / 2) {
             swipeRight = false;
             swipeLeft = false;
           }
   
           if (e.gesture.pointerType === "touch") {
             var $this = $(this);
             if (swipeLeft || swipeRight) {
               var fullWidth;
               if (swipeLeft) {
                 fullWidth = $this.innerWidth();
               } else {
                 fullWidth = -1 * $this.innerWidth();
               }
   
               $this.velocity({ translateX: fullWidth
               }, { duration: 100, queue: false, easing: 'easeOutQuad', complete: function () {
                   $this.css('border', 'none');
                   $this.velocity({ height: 0, padding: 0
                   }, { duration: 200, queue: false, easing: 'easeOutQuad', complete: function () {
                       $this.remove();
                     }
                   });
                 }
               });
             } else {
               $this.velocity({ translateX: 0
               }, { duration: 100, queue: false, easing: 'easeOutQuad' });
             }
             swipeLeft = false;
             swipeRight = false;
           }
         });
       });
   
       // time = 0
       // // Vertical Staggered list
       // $('ul.staggered-list.vertical li').velocity(
       //     { translateY: "100px"},
       //     { duration: 0 });
   
       // $('ul.staggered-list.vertical li').each(function() {
       //   $(this).velocity(
       //     { opacity: "1", translateY: "0"},
       //     { duration: 800, delay: time, easing: [60, 25] });
       //   time += 120;
       // });
   
       // // Fade in and Scale
       // $('.fade-in.scale').velocity(
       //     { scaleX: .4, scaleY: .4, translateX: -600},
       //     { duration: 0});
       // $('.fade-in').each(function() {
       //   $(this).velocity(
       //     { opacity: "1", scaleX: 1, scaleY: 1, translateX: 0},
       //     { duration: 800, easing: [60, 10] });
       // });
     });
   })(jQuery);
   ;(function ($) {
   
     var scrollFireEventsHandled = false;
   
     // Input: Array of JSON objects {selector, offset, callback}
     Materialize.scrollFire = function (options) {
       var onScroll = function () {
         var windowScroll = window.pageYOffset + window.innerHeight;
   
         for (var i = 0; i < options.length; i++) {
           // Get options from each line
           var value = options[i];
           var selector = value.selector,
               offset = value.offset,
               callback = value.callback;
   
           var currentElement = document.querySelector(selector);
           if (currentElement !== null) {
             var elementOffset = currentElement.getBoundingClientRect().top + window.pageYOffset;
   
             if (windowScroll > elementOffset + offset) {
               if (value.done !== true) {
                 if (typeof callback === 'function') {
                   callback.call(this, currentElement);
                 } else if (typeof callback === 'string') {
                   var callbackFunc = new Function(callback);
                   callbackFunc(currentElement);
                 }
                 value.done = true;
               }
             }
           }
         }
       };
   
       var throttledScroll = Materialize.throttle(function () {
         onScroll();
       }, options.throttle || 100);
   
       if (!scrollFireEventsHandled) {
         window.addEventListener("scroll", throttledScroll);
         window.addEventListener("resize", throttledScroll);
         scrollFireEventsHandled = true;
       }
   
       // perform a scan once, after current execution context, and after dom is ready
       setTimeout(throttledScroll, 0);
     };
   })(jQuery);
   ; /*!
     * pickadate.js v3.5.0, 2014/04/13
     * By Amsul, http://amsul.ca
     * Hosted on http://amsul.github.io/pickadate.js
     * Licensed under MIT
     */
   
   (function (factory) {
   
     Materialize.Picker = factory(jQuery);
   })(function ($) {
   
     var $window = $(window);
     var $document = $(document);
     var $html = $(document.documentElement);
   
     /**
      * The picker constructor that creates a blank picker.
      */
     function PickerConstructor(ELEMENT, NAME, COMPONENT, OPTIONS) {
   
       // If there’s no element, return the picker constructor.
       if (!ELEMENT) return PickerConstructor;
   
       var IS_DEFAULT_THEME = false,
   
   
       // The state of the picker.
       STATE = {
         id: ELEMENT.id || 'P' + Math.abs(~~(Math.random() * new Date()))
       },
   
   
       // Merge the defaults and options passed.
       SETTINGS = COMPONENT ? $.extend(true, {}, COMPONENT.defaults, OPTIONS) : OPTIONS || {},
   
   
       // Merge the default classes with the settings classes.
       CLASSES = $.extend({}, PickerConstructor.klasses(), SETTINGS.klass),
   
   
       // The element node wrapper into a jQuery object.
       $ELEMENT = $(ELEMENT),
   
   
       // Pseudo picker constructor.
       PickerInstance = function () {
         return this.start();
       },
   
   
       // The picker prototype.
       P = PickerInstance.prototype = {
   
         constructor: PickerInstance,
   
         $node: $ELEMENT,
   
         /**
          * Initialize everything
          */
         start: function () {
   
           // If it’s already started, do nothing.
           if (STATE && STATE.start) return P;
   
           // Update the picker states.
           STATE.methods = {};
           STATE.start = true;
           STATE.open = false;
           STATE.type = ELEMENT.type;
   
           // Confirm focus state, convert into text input to remove UA stylings,
           // and set as readonly to prevent keyboard popup.
           ELEMENT.autofocus = ELEMENT == getActiveElement();
           ELEMENT.readOnly = !SETTINGS.editable;
           ELEMENT.id = ELEMENT.id || STATE.id;
           if (ELEMENT.type != 'text') {
             ELEMENT.type = 'text';
           }
   
           // Create a new picker component with the settings.
           P.component = new COMPONENT(P, SETTINGS);
   
           // Create the picker root with a holder and then prepare it.
           P.$root = $(PickerConstructor._.node('div', createWrappedComponent(), CLASSES.picker, 'id="' + ELEMENT.id + '_root" tabindex="0"'));
           prepareElementRoot();
   
           // If there’s a format for the hidden input element, create the element.
           if (SETTINGS.formatSubmit) {
             prepareElementHidden();
           }
   
           // Prepare the input element.
           prepareElement();
   
           // Insert the root as specified in the settings.
           if (SETTINGS.container) $(SETTINGS.container).append(P.$root);else $ELEMENT.before(P.$root);
   
           // Bind the default component and settings events.
           P.on({
             start: P.component.onStart,
             render: P.component.onRender,
             stop: P.component.onStop,
             open: P.component.onOpen,
             close: P.component.onClose,
             set: P.component.onSet
           }).on({
             start: SETTINGS.onStart,
             render: SETTINGS.onRender,
             stop: SETTINGS.onStop,
             open: SETTINGS.onOpen,
             close: SETTINGS.onClose,
             set: SETTINGS.onSet
           });
   
           // Once we’re all set, check the theme in use.
           IS_DEFAULT_THEME = isUsingDefaultTheme(P.$root.children()[0]);
   
           // If the element has autofocus, open the picker.
           if (ELEMENT.autofocus) {
             P.open();
           }
   
           // Trigger queued the “start” and “render” events.
           return P.trigger('start').trigger('render');
         }, //start
   
   
         /**
          * Render a new picker
          */
         render: function (entireComponent) {
   
           // Insert a new component holder in the root or box.
           if (entireComponent) P.$root.html(createWrappedComponent());else P.$root.find('.' + CLASSES.box).html(P.component.nodes(STATE.open));
   
           // Trigger the queued “render” events.
           return P.trigger('render');
         }, //render
   
   
         /**
          * Destroy everything
          */
         stop: function () {
   
           // If it’s already stopped, do nothing.
           if (!STATE.start) return P;
   
           // Then close the picker.
           P.close();
   
           // Remove the hidden field.
           if (P._hidden) {
             P._hidden.parentNode.removeChild(P._hidden);
           }
   
           // Remove the root.
           P.$root.remove();
   
           // Remove the input class, remove the stored data, and unbind
           // the events (after a tick for IE - see `P.close`).
           $ELEMENT.removeClass(CLASSES.input).removeData(NAME);
           setTimeout(function () {
             $ELEMENT.off('.' + STATE.id);
           }, 0);
   
           // Restore the element state
           ELEMENT.type = STATE.type;
           ELEMENT.readOnly = false;
   
           // Trigger the queued “stop” events.
           P.trigger('stop');
   
           // Reset the picker states.
           STATE.methods = {};
           STATE.start = false;
   
           return P;
         }, //stop
   
   
         /**
          * Open up the picker
          */
         open: function (dontGiveFocus) {
   
           // If it’s already open, do nothing.
           if (STATE.open) return P;
   
           // Add the “active” class.
           $ELEMENT.addClass(CLASSES.active);
           aria(ELEMENT, 'expanded', true);
   
           // * A Firefox bug, when `html` has `overflow:hidden`, results in
           //   killing transitions :(. So add the “opened” state on the next tick.
           //   Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
           setTimeout(function () {
   
             // Add the “opened” class to the picker root.
             P.$root.addClass(CLASSES.opened);
             aria(P.$root[0], 'hidden', false);
           }, 0);
   
           // If we have to give focus, bind the element and doc events.
           if (dontGiveFocus !== false) {
   
             // Set it as open.
             STATE.open = true;
   
             // Prevent the page from scrolling.
             if (IS_DEFAULT_THEME) {
               $html.css('overflow', 'hidden').css('padding-right', '+=' + getScrollbarWidth());
             }
   
             // Pass focus to the root element’s jQuery object.
             // * Workaround for iOS8 to bring the picker’s root into view.
             P.$root.eq(0).focus();
   
             // Bind the document events.
             $document.on('click.' + STATE.id + ' focusin.' + STATE.id, function (event) {
   
               var target = event.target;
   
               // If the target of the event is not the element, close the picker picker.
               // * Don’t worry about clicks or focusins on the root because those don’t bubble up.
               //   Also, for Firefox, a click on an `option` element bubbles up directly
               //   to the doc. So make sure the target wasn't the doc.
               // * In Firefox stopPropagation() doesn’t prevent right-click events from bubbling,
               //   which causes the picker to unexpectedly close when right-clicking it. So make
               //   sure the event wasn’t a right-click.
               if (target != ELEMENT && target != document && event.which != 3) {
   
                 // If the target was the holder that covers the screen,
                 // keep the element focused to maintain tabindex.
                 P.close(target === P.$root.children()[0]);
               }
             }).on('keydown.' + STATE.id, function (event) {
   
               var
               // Get the keycode.
               keycode = event.keyCode,
   
   
               // Translate that to a selection change.
               keycodeToMove = P.component.key[keycode],
   
   
               // Grab the target.
               target = event.target;
   
               // On escape, close the picker and give focus.
               if (keycode == 27) {
                 P.close(true);
               }
   
               // Check if there is a key movement or “enter” keypress on the element.
               else if (target == P.$root[0] && (keycodeToMove || keycode == 13)) {
   
                   // Prevent the default action to stop page movement.
                   event.preventDefault();
   
                   // Trigger the key movement action.
                   if (keycodeToMove) {
                     PickerConstructor._.trigger(P.component.key.go, P, [PickerConstructor._.trigger(keycodeToMove)]);
                   }
   
                   // On “enter”, if the highlighted item isn’t disabled, set the value and close.
                   else if (!P.$root.find('.' + CLASSES.highlighted).hasClass(CLASSES.disabled)) {
                       P.set('select', P.component.item.highlight);
                       if (SETTINGS.closeOnSelect) {
                         P.close(true);
                       }
                     }
                 }
   
                 // If the target is within the root and “enter” is pressed,
                 // prevent the default action and trigger a click on the target instead.
                 else if ($.contains(P.$root[0], target) && keycode == 13) {
                     event.preventDefault();
                     target.click();
                   }
             });
           }
   
           // Trigger the queued “open” events.
           return P.trigger('open');
         }, //open
   
   
         /**
          * Close the picker
          */
         close: function (giveFocus) {
   
           // If we need to give focus, do it before changing states.
           if (giveFocus) {
             // ....ah yes! It would’ve been incomplete without a crazy workaround for IE :|
             // The focus is triggered *after* the close has completed - causing it
             // to open again. So unbind and rebind the event at the next tick.
             P.$root.off('focus.toOpen').eq(0).focus();
             setTimeout(function () {
               P.$root.on('focus.toOpen', handleFocusToOpenEvent);
             }, 0);
           }
   
           // Remove the “active” class.
           $ELEMENT.removeClass(CLASSES.active);
           aria(ELEMENT, 'expanded', false);
   
           // * A Firefox bug, when `html` has `overflow:hidden`, results in
           //   killing transitions :(. So remove the “opened” state on the next tick.
           //   Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
           setTimeout(function () {
   
             // Remove the “opened” and “focused” class from the picker root.
             P.$root.removeClass(CLASSES.opened + ' ' + CLASSES.focused);
             aria(P.$root[0], 'hidden', true);
           }, 0);
   
           // If it’s already closed, do nothing more.
           if (!STATE.open) return P;
   
           // Set it as closed.
           STATE.open = false;
   
           // Allow the page to scroll.
           if (IS_DEFAULT_THEME) {
             $html.css('overflow', '').css('padding-right', '-=' + getScrollbarWidth());
           }
   
           // Unbind the document events.
           $document.off('.' + STATE.id);
   
           // Trigger the queued “close” events.
           return P.trigger('close');
         }, //close
   
   
         /**
          * Clear the values
          */
         clear: function (options) {
           return P.set('clear', null, options);
         }, //clear
   
   
         /**
          * Set something
          */
         set: function (thing, value, options) {
   
           var thingItem,
               thingValue,
               thingIsObject = $.isPlainObject(thing),
               thingObject = thingIsObject ? thing : {};
   
           // Make sure we have usable options.
           options = thingIsObject && $.isPlainObject(value) ? value : options || {};
   
           if (thing) {
   
             // If the thing isn’t an object, make it one.
             if (!thingIsObject) {
               thingObject[thing] = value;
             }
   
             // Go through the things of items to set.
             for (thingItem in thingObject) {
   
               // Grab the value of the thing.
               thingValue = thingObject[thingItem];
   
               // First, if the item exists and there’s a value, set it.
               if (thingItem in P.component.item) {
                 if (thingValue === undefined) thingValue = null;
                 P.component.set(thingItem, thingValue, options);
               }
   
               // Then, check to update the element value and broadcast a change.
               if (thingItem == 'select' || thingItem == 'clear') {
                 $ELEMENT.val(thingItem == 'clear' ? '' : P.get(thingItem, SETTINGS.format)).trigger('change');
               }
             }
   
             // Render a new picker.
             P.render();
           }
   
           // When the method isn’t muted, trigger queued “set” events and pass the `thingObject`.
           return options.muted ? P : P.trigger('set', thingObject);
         }, //set
   
   
         /**
          * Get something
          */
         get: function (thing, format) {
   
           // Make sure there’s something to get.
           thing = thing || 'value';
   
           // If a picker state exists, return that.
           if (STATE[thing] != null) {
             return STATE[thing];
           }
   
           // Return the submission value, if that.
           if (thing == 'valueSubmit') {
             if (P._hidden) {
               return P._hidden.value;
             }
             thing = 'value';
           }
   
           // Return the value, if that.
           if (thing == 'value') {
             return ELEMENT.value;
           }
   
           // Check if a component item exists, return that.
           if (thing in P.component.item) {
             if (typeof format == 'string') {
               var thingValue = P.component.get(thing);
               return thingValue ? PickerConstructor._.trigger(P.component.formats.toString, P.component, [format, thingValue]) : '';
             }
             return P.component.get(thing);
           }
         }, //get
   
   
         /**
          * Bind events on the things.
          */
         on: function (thing, method, internal) {
   
           var thingName,
               thingMethod,
               thingIsObject = $.isPlainObject(thing),
               thingObject = thingIsObject ? thing : {};
   
           if (thing) {
   
             // If the thing isn’t an object, make it one.
             if (!thingIsObject) {
               thingObject[thing] = method;
             }
   
             // Go through the things to bind to.
             for (thingName in thingObject) {
   
               // Grab the method of the thing.
               thingMethod = thingObject[thingName];
   
               // If it was an internal binding, prefix it.
               if (internal) {
                 thingName = '_' + thingName;
               }
   
               // Make sure the thing methods collection exists.
               STATE.methods[thingName] = STATE.methods[thingName] || [];
   
               // Add the method to the relative method collection.
               STATE.methods[thingName].push(thingMethod);
             }
           }
   
           return P;
         }, //on
   
   
         /**
          * Unbind events on the things.
          */
         off: function () {
           var i,
               thingName,
               names = arguments;
           for (i = 0, namesCount = names.length; i < namesCount; i += 1) {
             thingName = names[i];
             if (thingName in STATE.methods) {
               delete STATE.methods[thingName];
             }
           }
           return P;
         },
   
         /**
          * Fire off method events.
          */
         trigger: function (name, data) {
           var _trigger = function (name) {
             var methodList = STATE.methods[name];
             if (methodList) {
               methodList.map(function (method) {
                 PickerConstructor._.trigger(method, P, [data]);
               });
             }
           };
           _trigger('_' + name);
           _trigger(name);
           return P;
         } //trigger
         //PickerInstance.prototype
   
   
         /**
          * Wrap the picker holder components together.
          */
       };function createWrappedComponent() {
   
         // Create a picker wrapper holder
         return PickerConstructor._.node('div',
   
         // Create a picker wrapper node
         PickerConstructor._.node('div',
   
         // Create a picker frame
         PickerConstructor._.node('div',
   
         // Create a picker box node
         PickerConstructor._.node('div',
   
         // Create the components nodes.
         P.component.nodes(STATE.open),
   
         // The picker box class
         CLASSES.box),
   
         // Picker wrap class
         CLASSES.wrap),
   
         // Picker frame class
         CLASSES.frame),
   
         // Picker holder class
         CLASSES.holder); //endreturn
       } //createWrappedComponent
   
   
       /**
        * Prepare the input element with all bindings.
        */
       function prepareElement() {
   
         $ELEMENT.
   
         // Store the picker data by component name.
         data(NAME, P).
   
         // Add the “input” class name.
         addClass(CLASSES.input).
   
         // Remove the tabindex.
         attr('tabindex', -1).
   
         // If there’s a `data-value`, update the value of the element.
         val($ELEMENT.data('value') ? P.get('select', SETTINGS.format) : ELEMENT.value);
   
         // Only bind keydown events if the element isn’t editable.
         if (!SETTINGS.editable) {
   
           $ELEMENT.
   
           // On focus/click, focus onto the root to open it up.
           on('focus.' + STATE.id + ' click.' + STATE.id, function (event) {
             event.preventDefault();
             P.$root.eq(0).focus();
           }).
   
           // Handle keyboard event based on the picker being opened or not.
           on('keydown.' + STATE.id, handleKeydownEvent);
         }
   
         // Update the aria attributes.
         aria(ELEMENT, {
           haspopup: true,
           expanded: false,
           readonly: false,
           owns: ELEMENT.id + '_root'
         });
       }
   
       /**
        * Prepare the root picker element with all bindings.
        */
       function prepareElementRoot() {
   
         P.$root.on({
   
           // For iOS8.
           keydown: handleKeydownEvent,
   
           // When something within the root is focused, stop from bubbling
           // to the doc and remove the “focused” state from the root.
           focusin: function (event) {
             P.$root.removeClass(CLASSES.focused);
             event.stopPropagation();
           },
   
           // When something within the root holder is clicked, stop it
           // from bubbling to the doc.
           'mousedown click': function (event) {
   
             var target = event.target;
   
             // Make sure the target isn’t the root holder so it can bubble up.
             if (target != P.$root.children()[0]) {
   
               event.stopPropagation();
   
               // * For mousedown events, cancel the default action in order to
               //   prevent cases where focus is shifted onto external elements
               //   when using things like jQuery mobile or MagnificPopup (ref: #249 & #120).
               //   Also, for Firefox, don’t prevent action on the `option` element.
               if (event.type == 'mousedown' && !$(target).is('input, select, textarea, button, option')) {
   
                 event.preventDefault();
   
                 // Re-focus onto the root so that users can click away
                 // from elements focused within the picker.
                 P.$root.eq(0).focus();
               }
             }
           }
         }).
   
         // Add/remove the “target” class on focus and blur.
         on({
           focus: function () {
             $ELEMENT.addClass(CLASSES.target);
           },
           blur: function () {
             $ELEMENT.removeClass(CLASSES.target);
           }
         }).
   
         // Open the picker and adjust the root “focused” state
         on('focus.toOpen', handleFocusToOpenEvent).
   
         // If there’s a click on an actionable element, carry out the actions.
         on('click', '[data-pick], [data-nav], [data-clear], [data-close]', function () {
   
           var $target = $(this),
               targetData = $target.data(),
               targetDisabled = $target.hasClass(CLASSES.navDisabled) || $target.hasClass(CLASSES.disabled),
   
   
           // * For IE, non-focusable elements can be active elements as well
           //   (http://stackoverflow.com/a/2684561).
           activeElement = getActiveElement();
           activeElement = activeElement && (activeElement.type || activeElement.href);
   
           // If it’s disabled or nothing inside is actively focused, re-focus the element.
           if (targetDisabled || activeElement && !$.contains(P.$root[0], activeElement)) {
             P.$root.eq(0).focus();
           }
   
           // If something is superficially changed, update the `highlight` based on the `nav`.
           if (!targetDisabled && targetData.nav) {
             P.set('highlight', P.component.item.highlight, { nav: targetData.nav });
           }
   
           // If something is picked, set `select` then close with focus.
           else if (!targetDisabled && 'pick' in targetData) {
               P.set('select', targetData.pick);
               if (SETTINGS.closeOnSelect) {
                 P.close(true);
               }
             }
   
             // If a “clear” button is pressed, empty the values and close with focus.
             else if (targetData.clear) {
                 P.clear();
                 if (SETTINGS.closeOnSelect) {
                   P.close(true);
                 }
               } else if (targetData.close) {
                 P.close(true);
               }
         }); //P.$root
   
         aria(P.$root[0], 'hidden', true);
       }
   
       /**
        * Prepare the hidden input element along with all bindings.
        */
       function prepareElementHidden() {
   
         var name;
   
         if (SETTINGS.hiddenName === true) {
           name = ELEMENT.name;
           ELEMENT.name = '';
         } else {
           name = [typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '', typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'];
           name = name[0] + ELEMENT.name + name[1];
         }
   
         P._hidden = $('<input ' + 'type=hidden ' +
   
         // Create the name using the original input’s with a prefix and suffix.
         'name="' + name + '"' + (
   
         // If the element has a value, set the hidden value as well.
         $ELEMENT.data('value') || ELEMENT.value ? ' value="' + P.get('select', SETTINGS.formatSubmit) + '"' : '') + '>')[0];
   
         $ELEMENT.
   
         // If the value changes, update the hidden input with the correct format.
         on('change.' + STATE.id, function () {
           P._hidden.value = ELEMENT.value ? P.get('select', SETTINGS.formatSubmit) : '';
         });
   
         // Insert the hidden input as specified in the settings.
         if (SETTINGS.container) $(SETTINGS.container).append(P._hidden);else $ELEMENT.before(P._hidden);
       }
   
       // For iOS8.
       function handleKeydownEvent(event) {
   
         var keycode = event.keyCode,
   
   
         // Check if one of the delete keys was pressed.
         isKeycodeDelete = /^(8|46)$/.test(keycode);
   
         // For some reason IE clears the input value on “escape”.
         if (keycode == 27) {
           P.close();
           return false;
         }
   
         // Check if `space` or `delete` was pressed or the picker is closed with a key movement.
         if (keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode]) {
   
           // Prevent it from moving the page and bubbling to doc.
           event.preventDefault();
           event.stopPropagation();
   
           // If `delete` was pressed, clear the values and close the picker.
           // Otherwise open the picker.
           if (isKeycodeDelete) {
             P.clear().close();
           } else {
             P.open();
           }
         }
       }
   
       // Separated for IE
       function handleFocusToOpenEvent(event) {
   
         // Stop the event from propagating to the doc.
         event.stopPropagation();
   
         // If it’s a focus event, add the “focused” class to the root.
         if (event.type == 'focus') {
           P.$root.addClass(CLASSES.focused);
         }
   
         // And then finally open the picker.
         P.open();
       }
   
       // Return a new picker instance.
       return new PickerInstance();
     } //PickerConstructor
   
   
     /**
      * The default classes and prefix to use for the HTML classes.
      */
     PickerConstructor.klasses = function (prefix) {
       prefix = prefix || 'picker';
       return {
   
         picker: prefix,
         opened: prefix + '--opened',
         focused: prefix + '--focused',
   
         input: prefix + '__input',
         active: prefix + '__input--active',
         target: prefix + '__input--target',
   
         holder: prefix + '__holder',
   
         frame: prefix + '__frame',
         wrap: prefix + '__wrap',
   
         box: prefix + '__box'
       };
     }; //PickerConstructor.klasses
   
   
     /**
      * Check if the default theme is being used.
      */
     function isUsingDefaultTheme(element) {
   
       var theme,
           prop = 'position';
   
       // For IE.
       if (element.currentStyle) {
         theme = element.currentStyle[prop];
       }
   
       // For normal browsers.
       else if (window.getComputedStyle) {
           theme = getComputedStyle(element)[prop];
         }
   
       return theme == 'fixed';
     }
   
     /**
      * Get the width of the browser’s scrollbar.
      * Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
      */
     function getScrollbarWidth() {
   
       if ($html.height() <= $window.height()) {
         return 0;
       }
   
       var $outer = $('<div style="visibility:hidden;width:100px" />').appendTo('body');
   
       // Get the width without scrollbars.
       var widthWithoutScroll = $outer[0].offsetWidth;
   
       // Force adding scrollbars.
       $outer.css('overflow', 'scroll');
   
       // Add the inner div.
       var $inner = $('<div style="width:100%" />').appendTo($outer);
   
       // Get the width with scrollbars.
       var widthWithScroll = $inner[0].offsetWidth;
   
       // Remove the divs.
       $outer.remove();
   
       // Return the difference between the widths.
       return widthWithoutScroll - widthWithScroll;
     }
   
     /**
      * PickerConstructor helper methods.
      */
     PickerConstructor._ = {
   
       /**
        * Create a group of nodes. Expects:
        * `
           {
               min:    {Integer},
               max:    {Integer},
               i:      {Integer},
               node:   {String},
               item:   {Function}
           }
        * `
        */
       group: function (groupObject) {
   
         var
         // Scope for the looped object
         loopObjectScope,
   
   
         // Create the nodes list
         nodesList = '',
   
   
         // The counter starts from the `min`
         counter = PickerConstructor._.trigger(groupObject.min, groupObject);
   
         // Loop from the `min` to `max`, incrementing by `i`
         for (; counter <= PickerConstructor._.trigger(groupObject.max, groupObject, [counter]); counter += groupObject.i) {
   
           // Trigger the `item` function within scope of the object
           loopObjectScope = PickerConstructor._.trigger(groupObject.item, groupObject, [counter]);
   
           // Splice the subgroup and create nodes out of the sub nodes
           nodesList += PickerConstructor._.node(groupObject.node, loopObjectScope[0], // the node
           loopObjectScope[1], // the classes
           loopObjectScope[2] // the attributes
           );
         }
   
         // Return the list of nodes
         return nodesList;
       }, //group
   
   
       /**
        * Create a dom node string
        */
       node: function (wrapper, item, klass, attribute) {
   
         // If the item is false-y, just return an empty string
         if (!item) return '';
   
         // If the item is an array, do a join
         item = $.isArray(item) ? item.join('') : item;
   
         // Check for the class
         klass = klass ? ' class="' + klass + '"' : '';
   
         // Check for any attributes
         attribute = attribute ? ' ' + attribute : '';
   
         // Return the wrapped item
         return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>';
       }, //node
   
   
       /**
        * Lead numbers below 10 with a zero.
        */
       lead: function (number) {
         return (number < 10 ? '0' : '') + number;
       },
   
       /**
        * Trigger a function otherwise return the value.
        */
       trigger: function (callback, scope, args) {
         return typeof callback == 'function' ? callback.apply(scope, args || []) : callback;
       },
   
       /**
        * If the second character is a digit, length is 2 otherwise 1.
        */
       digits: function (string) {
         return (/\d/.test(string[1]) ? 2 : 1
         );
       },
   
       /**
        * Tell if something is a date object.
        */
       isDate: function (value) {
         return {}.toString.call(value).indexOf('Date') > -1 && this.isInteger(value.getDate());
       },
   
       /**
        * Tell if something is an integer.
        */
       isInteger: function (value) {
         return {}.toString.call(value).indexOf('Number') > -1 && value % 1 === 0;
       },
   
       /**
        * Create ARIA attribute strings.
        */
       ariaAttr: ariaAttr //PickerConstructor._
   
   
       /**
        * Extend the picker with a component and defaults.
        */
     };PickerConstructor.extend = function (name, Component) {
   
       // Extend jQuery.
       $.fn[name] = function (options, action) {
   
         // Grab the component data.
         var componentData = this.data(name);
   
         // If the picker is requested, return the data object.
         if (options == 'picker') {
           return componentData;
         }
   
         // If the component data exists and `options` is a string, carry out the action.
         if (componentData && typeof options == 'string') {
           return PickerConstructor._.trigger(componentData[options], componentData, [action]);
         }
   
         // Otherwise go through each matched element and if the component
         // doesn’t exist, create a new picker using `this` element
         // and merging the defaults and options with a deep copy.
         return this.each(function () {
           var $this = $(this);
           if (!$this.data(name)) {
             new PickerConstructor(this, name, Component, options);
           }
         });
       };
   
       // Set the defaults.
       $.fn[name].defaults = Component.defaults;
     }; //PickerConstructor.extend
   
   
     function aria(element, attribute, value) {
       if ($.isPlainObject(attribute)) {
         for (var key in attribute) {
           ariaSet(element, key, attribute[key]);
         }
       } else {
         ariaSet(element, attribute, value);
       }
     }
     function ariaSet(element, attribute, value) {
       element.setAttribute((attribute == 'role' ? '' : 'aria-') + attribute, value);
     }
     function ariaAttr(attribute, data) {
       if (!$.isPlainObject(attribute)) {
         attribute = { attribute: data };
       }
       data = '';
       for (var key in attribute) {
         var attr = (key == 'role' ? '' : 'aria-') + key,
             attrVal = attribute[key];
         data += attrVal == null ? '' : attr + '="' + attribute[key] + '"';
       }
       return data;
     }
   
     // IE8 bug throws an error for activeElements within iframes.
     function getActiveElement() {
       try {
         return document.activeElement;
       } catch (err) {}
     }
   
     // Expose the picker constructor.
     return PickerConstructor;
   });
   ; /*!
     * Date picker for pickadate.js v3.5.0
     * http://amsul.github.io/pickadate.js/date.htm
     */
   
   (function (factory) {
     factory(Materialize.Picker, jQuery);
   })(function (Picker, $) {
   
     /**
      * Globals and constants
      */
     var DAYS_IN_WEEK = 7,
         WEEKS_IN_CALENDAR = 6,
         _ = Picker._;
   
     /**
      * The date picker constructor
      */
     function DatePicker(picker, settings) {
   
       var calendar = this,
           element = picker.$node[0],
           elementValue = element.value,
           elementDataValue = picker.$node.data('value'),
           valueString = elementDataValue || elementValue,
           formatString = elementDataValue ? settings.formatSubmit : settings.format,
           isRTL = function () {
   
         return element.currentStyle ?
   
         // For IE.
         element.currentStyle.direction == 'rtl' :
   
         // For normal browsers.
         getComputedStyle(picker.$root[0]).direction == 'rtl';
       };
   
       calendar.settings = settings;
       calendar.$node = picker.$node;
   
       // The queue of methods that will be used to build item objects.
       calendar.queue = {
         min: 'measure create',
         max: 'measure create',
         now: 'now create',
         select: 'parse create validate',
         highlight: 'parse navigate create validate',
         view: 'parse create validate viewset',
         disable: 'deactivate',
         enable: 'activate'
   
         // The component's item object.
       };calendar.item = {};
   
       calendar.item.clear = null;
       calendar.item.disable = (settings.disable || []).slice(0);
       calendar.item.enable = -function (collectionDisabled) {
         return collectionDisabled[0] === true ? collectionDisabled.shift() : -1;
       }(calendar.item.disable);
   
       calendar.set('min', settings.min).set('max', settings.max).set('now');
   
       // When there’s a value, set the `select`, which in turn
       // also sets the `highlight` and `view`.
       if (valueString) {
         calendar.set('select', valueString, { format: formatString });
       }
   
       // If there’s no value, default to highlighting “today”.
       else {
           calendar.set('select', null).set('highlight', calendar.item.now);
         }
   
       // The keycode to movement mapping.
       calendar.key = {
         40: 7, // Down
         38: -7, // Up
         39: function () {
           return isRTL() ? -1 : 1;
         }, // Right
         37: function () {
           return isRTL() ? 1 : -1;
         }, // Left
         go: function (timeChange) {
           var highlightedObject = calendar.item.highlight,
               targetDate = new Date(highlightedObject.year, highlightedObject.month, highlightedObject.date + timeChange);
           calendar.set('highlight', targetDate, { interval: timeChange });
           this.render();
         }
   
         // Bind some picker events.
       };picker.on('render', function () {
         picker.$root.find('.' + settings.klass.selectMonth).on('change', function () {
           var value = this.value;
           if (value) {
             picker.set('highlight', [picker.get('view').year, value, picker.get('highlight').date]);
             picker.$root.find('.' + settings.klass.selectMonth).trigger('focus');
           }
         });
         picker.$root.find('.' + settings.klass.selectYear).on('change', function () {
           var value = this.value;
           if (value) {
             picker.set('highlight', [value, picker.get('view').month, picker.get('highlight').date]);
             picker.$root.find('.' + settings.klass.selectYear).trigger('focus');
           }
         });
       }, 1).on('open', function () {
         var includeToday = '';
         if (calendar.disabled(calendar.get('now'))) {
           includeToday = ':not(.' + settings.klass.buttonToday + ')';
         }
         picker.$root.find('button' + includeToday + ', select').attr('disabled', false);
       }, 1).on('close', function () {
         picker.$root.find('button, select').attr('disabled', true);
       }, 1);
     } //DatePicker
   
   
     /**
      * Set a datepicker item object.
      */
     DatePicker.prototype.set = function (type, value, options) {
   
       var calendar = this,
           calendarItem = calendar.item;
   
       // If the value is `null` just set it immediately.
       if (value === null) {
         if (type == 'clear') type = 'select';
         calendarItem[type] = value;
         return calendar;
       }
   
       // Otherwise go through the queue of methods, and invoke the functions.
       // Update this as the time unit, and set the final value as this item.
       // * In the case of `enable`, keep the queue but set `disable` instead.
       //   And in the case of `flip`, keep the queue but set `enable` instead.
       calendarItem[type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type] = calendar.queue[type].split(' ').map(function (method) {
         value = calendar[method](type, value, options);
         return value;
       }).pop();
   
       // Check if we need to cascade through more updates.
       if (type == 'select') {
         calendar.set('highlight', calendarItem.select, options);
       } else if (type == 'highlight') {
         calendar.set('view', calendarItem.highlight, options);
       } else if (type.match(/^(flip|min|max|disable|enable)$/)) {
         if (calendarItem.select && calendar.disabled(calendarItem.select)) {
           calendar.set('select', calendarItem.select, options);
         }
         if (calendarItem.highlight && calendar.disabled(calendarItem.highlight)) {
           calendar.set('highlight', calendarItem.highlight, options);
         }
       }
   
       return calendar;
     }; //DatePicker.prototype.set
   
   
     /**
      * Get a datepicker item object.
      */
     DatePicker.prototype.get = function (type) {
       return this.item[type];
     }; //DatePicker.prototype.get
   
   
     /**
      * Create a picker date object.
      */
     DatePicker.prototype.create = function (type, value, options) {
   
       var isInfiniteValue,
           calendar = this;
   
       // If there’s no value, use the type as the value.
       value = value === undefined ? type : value;
   
       // If it’s infinity, update the value.
       if (value == -Infinity || value == Infinity) {
         isInfiniteValue = value;
       }
   
       // If it’s an object, use the native date object.
       else if ($.isPlainObject(value) && _.isInteger(value.pick)) {
           value = value.obj;
         }
   
         // If it’s an array, convert it into a date and make sure
         // that it’s a valid date – otherwise default to today.
         else if ($.isArray(value)) {
             value = new Date(value[0], value[1], value[2]);
             value = _.isDate(value) ? value : calendar.create().obj;
           }
   
           // If it’s a number or date object, make a normalized date.
           else if (_.isInteger(value) || _.isDate(value)) {
               value = calendar.normalize(new Date(value), options);
             }
   
             // If it’s a literal true or any other case, set it to now.
             else /*if ( value === true )*/{
                 value = calendar.now(type, value, options);
               }
   
       // Return the compiled object.
       return {
         year: isInfiniteValue || value.getFullYear(),
         month: isInfiniteValue || value.getMonth(),
         date: isInfiniteValue || value.getDate(),
         day: isInfiniteValue || value.getDay(),
         obj: isInfiniteValue || value,
         pick: isInfiniteValue || value.getTime()
       };
     }; //DatePicker.prototype.create
   
   
     /**
      * Create a range limit object using an array, date object,
      * literal “true”, or integer relative to another time.
      */
     DatePicker.prototype.createRange = function (from, to) {
   
       var calendar = this,
           createDate = function (date) {
         if (date === true || $.isArray(date) || _.isDate(date)) {
           return calendar.create(date);
         }
         return date;
       };
   
       // Create objects if possible.
       if (!_.isInteger(from)) {
         from = createDate(from);
       }
       if (!_.isInteger(to)) {
         to = createDate(to);
       }
   
       // Create relative dates.
       if (_.isInteger(from) && $.isPlainObject(to)) {
         from = [to.year, to.month, to.date + from];
       } else if (_.isInteger(to) && $.isPlainObject(from)) {
         to = [from.year, from.month, from.date + to];
       }
   
       return {
         from: createDate(from),
         to: createDate(to)
       };
     }; //DatePicker.prototype.createRange
   
   
     /**
      * Check if a date unit falls within a date range object.
      */
     DatePicker.prototype.withinRange = function (range, dateUnit) {
       range = this.createRange(range.from, range.to);
       return dateUnit.pick >= range.from.pick && dateUnit.pick <= range.to.pick;
     };
   
     /**
      * Check if two date range objects overlap.
      */
     DatePicker.prototype.overlapRanges = function (one, two) {
   
       var calendar = this;
   
       // Convert the ranges into comparable dates.
       one = calendar.createRange(one.from, one.to);
       two = calendar.createRange(two.from, two.to);
   
       return calendar.withinRange(one, two.from) || calendar.withinRange(one, two.to) || calendar.withinRange(two, one.from) || calendar.withinRange(two, one.to);
     };
   
     /**
      * Get the date today.
      */
     DatePicker.prototype.now = function (type, value, options) {
       value = new Date();
       if (options && options.rel) {
         value.setDate(value.getDate() + options.rel);
       }
       return this.normalize(value, options);
     };
   
     /**
      * Navigate to next/prev month.
      */
     DatePicker.prototype.navigate = function (type, value, options) {
   
       var targetDateObject,
           targetYear,
           targetMonth,
           targetDate,
           isTargetArray = $.isArray(value),
           isTargetObject = $.isPlainObject(value),
           viewsetObject = this.item.view; /*,
                                           safety = 100*/
   
       if (isTargetArray || isTargetObject) {
   
         if (isTargetObject) {
           targetYear = value.year;
           targetMonth = value.month;
           targetDate = value.date;
         } else {
           targetYear = +value[0];
           targetMonth = +value[1];
           targetDate = +value[2];
         }
   
         // If we’re navigating months but the view is in a different
         // month, navigate to the view’s year and month.
         if (options && options.nav && viewsetObject && viewsetObject.month !== targetMonth) {
           targetYear = viewsetObject.year;
           targetMonth = viewsetObject.month;
         }
   
         // Figure out the expected target year and month.
         targetDateObject = new Date(targetYear, targetMonth + (options && options.nav ? options.nav : 0), 1);
         targetYear = targetDateObject.getFullYear();
         targetMonth = targetDateObject.getMonth();
   
         // If the month we’re going to doesn’t have enough days,
         // keep decreasing the date until we reach the month’s last date.
         while ( /*safety &&*/new Date(targetYear, targetMonth, targetDate).getMonth() !== targetMonth) {
           targetDate -= 1;
           /*safety -= 1
           if ( !safety ) {
               throw 'Fell into an infinite loop while navigating to ' + new Date( targetYear, targetMonth, targetDate ) + '.'
           }*/
         }
   
         value = [targetYear, targetMonth, targetDate];
       }
   
       return value;
     }; //DatePicker.prototype.navigate
   
   
     /**
      * Normalize a date by setting the hours to midnight.
      */
     DatePicker.prototype.normalize = function (value /*, options*/) {
       value.setHours(0, 0, 0, 0);
       return value;
     };
   
     /**
      * Measure the range of dates.
      */
     DatePicker.prototype.measure = function (type, value /*, options*/) {
   
       var calendar = this;
   
       // If it’s anything false-y, remove the limits.
       if (!value) {
         value = type == 'min' ? -Infinity : Infinity;
       }
   
       // If it’s a string, parse it.
       else if (typeof value == 'string') {
           value = calendar.parse(type, value);
         }
   
         // If it's an integer, get a date relative to today.
         else if (_.isInteger(value)) {
             value = calendar.now(type, value, { rel: value });
           }
   
       return value;
     }; ///DatePicker.prototype.measure
   
   
     /**
      * Create a viewset object based on navigation.
      */
     DatePicker.prototype.viewset = function (type, dateObject /*, options*/) {
       return this.create([dateObject.year, dateObject.month, 1]);
     };
   
     /**
      * Validate a date as enabled and shift if needed.
      */
     DatePicker.prototype.validate = function (type, dateObject, options) {
   
       var calendar = this,
   
   
       // Keep a reference to the original date.
       originalDateObject = dateObject,
   
   
       // Make sure we have an interval.
       interval = options && options.interval ? options.interval : 1,
   
   
       // Check if the calendar enabled dates are inverted.
       isFlippedBase = calendar.item.enable === -1,
   
   
       // Check if we have any enabled dates after/before now.
       hasEnabledBeforeTarget,
           hasEnabledAfterTarget,
   
   
       // The min & max limits.
       minLimitObject = calendar.item.min,
           maxLimitObject = calendar.item.max,
   
   
       // Check if we’ve reached the limit during shifting.
       reachedMin,
           reachedMax,
   
   
       // Check if the calendar is inverted and at least one weekday is enabled.
       hasEnabledWeekdays = isFlippedBase && calendar.item.disable.filter(function (value) {
   
         // If there’s a date, check where it is relative to the target.
         if ($.isArray(value)) {
           var dateTime = calendar.create(value).pick;
           if (dateTime < dateObject.pick) hasEnabledBeforeTarget = true;else if (dateTime > dateObject.pick) hasEnabledAfterTarget = true;
         }
   
         // Return only integers for enabled weekdays.
         return _.isInteger(value);
       }).length; /*,
                  safety = 100*/
   
       // Cases to validate for:
       // [1] Not inverted and date disabled.
       // [2] Inverted and some dates enabled.
       // [3] Not inverted and out of range.
       //
       // Cases to **not** validate for:
       // • Navigating months.
       // • Not inverted and date enabled.
       // • Inverted and all dates disabled.
       // • ..and anything else.
       if (!options || !options.nav) if (
       /* 1 */!isFlippedBase && calendar.disabled(dateObject) ||
       /* 2 */isFlippedBase && calendar.disabled(dateObject) && (hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget) ||
       /* 3 */!isFlippedBase && (dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick)) {
   
         // When inverted, flip the direction if there aren’t any enabled weekdays
         // and there are no enabled dates in the direction of the interval.
         if (isFlippedBase && !hasEnabledWeekdays && (!hasEnabledAfterTarget && interval > 0 || !hasEnabledBeforeTarget && interval < 0)) {
           interval *= -1;
         }
   
         // Keep looping until we reach an enabled date.
         while ( /*safety &&*/calendar.disabled(dateObject)) {
   
           /*safety -= 1
           if ( !safety ) {
               throw 'Fell into an infinite loop while validating ' + dateObject.obj + '.'
           }*/
   
           // If we’ve looped into the next/prev month with a large interval, return to the original date and flatten the interval.
           if (Math.abs(interval) > 1 && (dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month)) {
             dateObject = originalDateObject;
             interval = interval > 0 ? 1 : -1;
           }
   
           // If we’ve reached the min/max limit, reverse the direction, flatten the interval and set it to the limit.
           if (dateObject.pick <= minLimitObject.pick) {
             reachedMin = true;
             interval = 1;
             dateObject = calendar.create([minLimitObject.year, minLimitObject.month, minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1)]);
           } else if (dateObject.pick >= maxLimitObject.pick) {
             reachedMax = true;
             interval = -1;
             dateObject = calendar.create([maxLimitObject.year, maxLimitObject.month, maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1)]);
           }
   
           // If we’ve reached both limits, just break out of the loop.
           if (reachedMin && reachedMax) {
             break;
           }
   
           // Finally, create the shifted date using the interval and keep looping.
           dateObject = calendar.create([dateObject.year, dateObject.month, dateObject.date + interval]);
         }
       } //endif
   
   
       // Return the date object settled on.
       return dateObject;
     }; //DatePicker.prototype.validate
   
   
     /**
      * Check if a date is disabled.
      */
     DatePicker.prototype.disabled = function (dateToVerify) {
   
       var calendar = this,
   
   
       // Filter through the disabled dates to check if this is one.
       isDisabledMatch = calendar.item.disable.filter(function (dateToDisable) {
   
         // If the date is a number, match the weekday with 0index and `firstDay` check.
         if (_.isInteger(dateToDisable)) {
           return dateToVerify.day === (calendar.settings.firstDay ? dateToDisable : dateToDisable - 1) % 7;
         }
   
         // If it’s an array or a native JS date, create and match the exact date.
         if ($.isArray(dateToDisable) || _.isDate(dateToDisable)) {
           return dateToVerify.pick === calendar.create(dateToDisable).pick;
         }
   
         // If it’s an object, match a date within the “from” and “to” range.
         if ($.isPlainObject(dateToDisable)) {
           return calendar.withinRange(dateToDisable, dateToVerify);
         }
       });
   
       // If this date matches a disabled date, confirm it’s not inverted.
       isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function (dateToDisable) {
         return $.isArray(dateToDisable) && dateToDisable[3] == 'inverted' || $.isPlainObject(dateToDisable) && dateToDisable.inverted;
       }).length;
   
       // Check the calendar “enabled” flag and respectively flip the
       // disabled state. Then also check if it’s beyond the min/max limits.
       return calendar.item.enable === -1 ? !isDisabledMatch : isDisabledMatch || dateToVerify.pick < calendar.item.min.pick || dateToVerify.pick > calendar.item.max.pick;
     }; //DatePicker.prototype.disabled
   
   
     /**
      * Parse a string into a usable type.
      */
     DatePicker.prototype.parse = function (type, value, options) {
   
       var calendar = this,
           parsingObject = {};
   
       // If it’s already parsed, we’re good.
       if (!value || typeof value != 'string') {
         return value;
       }
   
       // We need a `.format` to parse the value with.
       if (!(options && options.format)) {
         options = options || {};
         options.format = calendar.settings.format;
       }
   
       // Convert the format into an array and then map through it.
       calendar.formats.toArray(options.format).map(function (label) {
   
         var
         // Grab the formatting label.
         formattingLabel = calendar.formats[label],
   
   
         // The format length is from the formatting label function or the
         // label length without the escaping exclamation (!) mark.
         formatLength = formattingLabel ? _.trigger(formattingLabel, calendar, [value, parsingObject]) : label.replace(/^!/, '').length;
   
         // If there's a format label, split the value up to the format length.
         // Then add it to the parsing object with appropriate label.
         if (formattingLabel) {
           parsingObject[label] = value.substr(0, formatLength);
         }
   
         // Update the value as the substring from format length to end.
         value = value.substr(formatLength);
       });
   
       // Compensate for month 0index.
       return [parsingObject.yyyy || parsingObject.yy, +(parsingObject.mm || parsingObject.m) - 1, parsingObject.dd || parsingObject.d];
     }; //DatePicker.prototype.parse
   
   
     /**
      * Various formats to display the object in.
      */
     DatePicker.prototype.formats = function () {
   
       // Return the length of the first word in a collection.
       function getWordLengthFromCollection(string, collection, dateObject) {
   
         // Grab the first word from the string.
         var word = string.match(/\w+/)[0];
   
         // If there's no month index, add it to the date object
         if (!dateObject.mm && !dateObject.m) {
           dateObject.m = collection.indexOf(word) + 1;
         }
   
         // Return the length of the word.
         return word.length;
       }
   
       // Get the length of the first word in a string.
       function getFirstWordLength(string) {
         return string.match(/\w+/)[0].length;
       }
   
       return {
   
         d: function (string, dateObject) {
   
           // If there's string, then get the digits length.
           // Otherwise return the selected date.
           return string ? _.digits(string) : dateObject.date;
         },
         dd: function (string, dateObject) {
   
           // If there's a string, then the length is always 2.
           // Otherwise return the selected date with a leading zero.
           return string ? 2 : _.lead(dateObject.date);
         },
         ddd: function (string, dateObject) {
   
           // If there's a string, then get the length of the first word.
           // Otherwise return the short selected weekday.
           return string ? getFirstWordLength(string) : this.settings.weekdaysShort[dateObject.day];
         },
         dddd: function (string, dateObject) {
   
           // If there's a string, then get the length of the first word.
           // Otherwise return the full selected weekday.
           return string ? getFirstWordLength(string) : this.settings.weekdaysFull[dateObject.day];
         },
         m: function (string, dateObject) {
   
           // If there's a string, then get the length of the digits
           // Otherwise return the selected month with 0index compensation.
           return string ? _.digits(string) : dateObject.month + 1;
         },
         mm: function (string, dateObject) {
   
           // If there's a string, then the length is always 2.
           // Otherwise return the selected month with 0index and leading zero.
           return string ? 2 : _.lead(dateObject.month + 1);
         },
         mmm: function (string, dateObject) {
   
           var collection = this.settings.monthsShort;
   
           // If there's a string, get length of the relevant month from the short
           // months collection. Otherwise return the selected month from that collection.
           return string ? getWordLengthFromCollection(string, collection, dateObject) : collection[dateObject.month];
         },
         mmmm: function (string, dateObject) {
   
           var collection = this.settings.monthsFull;
   
           // If there's a string, get length of the relevant month from the full
           // months collection. Otherwise return the selected month from that collection.
           return string ? getWordLengthFromCollection(string, collection, dateObject) : collection[dateObject.month];
         },
         yy: function (string, dateObject) {
   
           // If there's a string, then the length is always 2.
           // Otherwise return the selected year by slicing out the first 2 digits.
           return string ? 2 : ('' + dateObject.year).slice(2);
         },
         yyyy: function (string, dateObject) {
   
           // If there's a string, then the length is always 4.
           // Otherwise return the selected year.
           return string ? 4 : dateObject.year;
         },
   
         // Create an array by splitting the formatting string passed.
         toArray: function (formatString) {
           return formatString.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g);
         },
   
         // Format an object into a string using the formatting options.
         toString: function (formatString, itemObject) {
           var calendar = this;
           return calendar.formats.toArray(formatString).map(function (label) {
             return _.trigger(calendar.formats[label], calendar, [0, itemObject]) || label.replace(/^!/, '');
           }).join('');
         }
       };
     }(); //DatePicker.prototype.formats
   
   
     /**
      * Check if two date units are the exact.
      */
     DatePicker.prototype.isDateExact = function (one, two) {
   
       var calendar = this;
   
       // When we’re working with weekdays, do a direct comparison.
       if (_.isInteger(one) && _.isInteger(two) || typeof one == 'boolean' && typeof two == 'boolean') {
         return one === two;
       }
   
       // When we’re working with date representations, compare the “pick” value.
       if ((_.isDate(one) || $.isArray(one)) && (_.isDate(two) || $.isArray(two))) {
         return calendar.create(one).pick === calendar.create(two).pick;
       }
   
       // When we’re working with range objects, compare the “from” and “to”.
       if ($.isPlainObject(one) && $.isPlainObject(two)) {
         return calendar.isDateExact(one.from, two.from) && calendar.isDateExact(one.to, two.to);
       }
   
       return false;
     };
   
     /**
      * Check if two date units overlap.
      */
     DatePicker.prototype.isDateOverlap = function (one, two) {
   
       var calendar = this,
           firstDay = calendar.settings.firstDay ? 1 : 0;
   
       // When we’re working with a weekday index, compare the days.
       if (_.isInteger(one) && (_.isDate(two) || $.isArray(two))) {
         one = one % 7 + firstDay;
         return one === calendar.create(two).day + 1;
       }
       if (_.isInteger(two) && (_.isDate(one) || $.isArray(one))) {
         two = two % 7 + firstDay;
         return two === calendar.create(one).day + 1;
       }
   
       // When we’re working with range objects, check if the ranges overlap.
       if ($.isPlainObject(one) && $.isPlainObject(two)) {
         return calendar.overlapRanges(one, two);
       }
   
       return false;
     };
   
     /**
      * Flip the “enabled” state.
      */
     DatePicker.prototype.flipEnable = function (val) {
       var itemObject = this.item;
       itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1);
     };
   
     /**
      * Mark a collection of dates as “disabled”.
      */
     DatePicker.prototype.deactivate = function (type, datesToDisable) {
   
       var calendar = this,
           disabledItems = calendar.item.disable.slice(0);
   
       // If we’re flipping, that’s all we need to do.
       if (datesToDisable == 'flip') {
         calendar.flipEnable();
       } else if (datesToDisable === false) {
         calendar.flipEnable(1);
         disabledItems = [];
       } else if (datesToDisable === true) {
         calendar.flipEnable(-1);
         disabledItems = [];
       }
   
       // Otherwise go through the dates to disable.
       else {
   
           datesToDisable.map(function (unitToDisable) {
   
             var matchFound;
   
             // When we have disabled items, check for matches.
             // If something is matched, immediately break out.
             for (var index = 0; index < disabledItems.length; index += 1) {
               if (calendar.isDateExact(unitToDisable, disabledItems[index])) {
                 matchFound = true;
                 break;
               }
             }
   
             // If nothing was found, add the validated unit to the collection.
             if (!matchFound) {
               if (_.isInteger(unitToDisable) || _.isDate(unitToDisable) || $.isArray(unitToDisable) || $.isPlainObject(unitToDisable) && unitToDisable.from && unitToDisable.to) {
                 disabledItems.push(unitToDisable);
               }
             }
           });
         }
   
       // Return the updated collection.
       return disabledItems;
     }; //DatePicker.prototype.deactivate
   
   
     /**
      * Mark a collection of dates as “enabled”.
      */
     DatePicker.prototype.activate = function (type, datesToEnable) {
   
       var calendar = this,
           disabledItems = calendar.item.disable,
           disabledItemsCount = disabledItems.length;
   
       // If we’re flipping, that’s all we need to do.
       if (datesToEnable == 'flip') {
         calendar.flipEnable();
       } else if (datesToEnable === true) {
         calendar.flipEnable(1);
         disabledItems = [];
       } else if (datesToEnable === false) {
         calendar.flipEnable(-1);
         disabledItems = [];
       }
   
       // Otherwise go through the disabled dates.
       else {
   
           datesToEnable.map(function (unitToEnable) {
   
             var matchFound, disabledUnit, index, isExactRange;
   
             // Go through the disabled items and try to find a match.
             for (index = 0; index < disabledItemsCount; index += 1) {
   
               disabledUnit = disabledItems[index];
   
               // When an exact match is found, remove it from the collection.
               if (calendar.isDateExact(disabledUnit, unitToEnable)) {
                 matchFound = disabledItems[index] = null;
                 isExactRange = true;
                 break;
               }
   
               // When an overlapped match is found, add the “inverted” state to it.
               else if (calendar.isDateOverlap(disabledUnit, unitToEnable)) {
                   if ($.isPlainObject(unitToEnable)) {
                     unitToEnable.inverted = true;
                     matchFound = unitToEnable;
                   } else if ($.isArray(unitToEnable)) {
                     matchFound = unitToEnable;
                     if (!matchFound[3]) matchFound.push('inverted');
                   } else if (_.isDate(unitToEnable)) {
                     matchFound = [unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted'];
                   }
                   break;
                 }
             }
   
             // If a match was found, remove a previous duplicate entry.
             if (matchFound) for (index = 0; index < disabledItemsCount; index += 1) {
               if (calendar.isDateExact(disabledItems[index], unitToEnable)) {
                 disabledItems[index] = null;
                 break;
               }
             }
   
             // In the event that we’re dealing with an exact range of dates,
             // make sure there are no “inverted” dates because of it.
             if (isExactRange) for (index = 0; index < disabledItemsCount; index += 1) {
               if (calendar.isDateOverlap(disabledItems[index], unitToEnable)) {
                 disabledItems[index] = null;
                 break;
               }
             }
   
             // If something is still matched, add it into the collection.
             if (matchFound) {
               disabledItems.push(matchFound);
             }
           });
         }
   
       // Return the updated collection.
       return disabledItems.filter(function (val) {
         return val != null;
       });
     }; //DatePicker.prototype.activate
   
   
     /**
      * Create a string for the nodes in the picker.
      */
     DatePicker.prototype.nodes = function (isOpen) {
   
       var calendar = this,
           settings = calendar.settings,
           calendarItem = calendar.item,
           nowObject = calendarItem.now,
           selectedObject = calendarItem.select,
           highlightedObject = calendarItem.highlight,
           viewsetObject = calendarItem.view,
           disabledCollection = calendarItem.disable,
           minLimitObject = calendarItem.min,
           maxLimitObject = calendarItem.max,
   
   
       // Create the calendar table head using a copy of weekday labels collection.
       // * We do a copy so we don't mutate the original array.
       tableHead = function (collection, fullCollection) {
   
         // If the first day should be Monday, move Sunday to the end.
         if (settings.firstDay) {
           collection.push(collection.shift());
           fullCollection.push(fullCollection.shift());
         }
   
         // Create and return the table head group.
         return _.node('thead', _.node('tr', _.group({
           min: 0,
           max: DAYS_IN_WEEK - 1,
           i: 1,
           node: 'th',
           item: function (counter) {
             return [collection[counter], settings.klass.weekdays, 'scope=col title="' + fullCollection[counter] + '"'];
           }
         }))); //endreturn
   
         // Materialize modified
       }((settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysLetter).slice(0), settings.weekdaysFull.slice(0)),
           //tableHead
   
   
       // Create the nav for next/prev month.
       createMonthNav = function (next) {
   
         // Otherwise, return the created month tag.
         return _.node('div', ' ', settings.klass['nav' + (next ? 'Next' : 'Prev')] + (
   
         // If the focused month is outside the range, disabled the button.
         next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month || !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ? ' ' + settings.klass.navDisabled : ''), 'data-nav=' + (next || -1) + ' ' + _.ariaAttr({
           role: 'button',
           controls: calendar.$node[0].id + '_table'
         }) + ' ' + 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev) + '"'); //endreturn
       },
           //createMonthNav
   
   
       // Create the month label.
       //Materialize modified
       createMonthLabel = function (override) {
   
         var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull;
   
         // Materialize modified
         if (override == "short_months") {
           monthsCollection = settings.monthsShort;
         }
   
         // If there are months to select, add a dropdown menu.
         if (settings.selectMonths && override == undefined) {
   
           return _.node('select', _.group({
             min: 0,
             max: 11,
             i: 1,
             node: 'option',
             item: function (loopedMonth) {
   
               return [
   
               // The looped month and no classes.
               monthsCollection[loopedMonth], 0,
   
               // Set the value and selected index.
               'value=' + loopedMonth + (viewsetObject.month == loopedMonth ? ' selected' : '') + (viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month || viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month ? ' disabled' : '')];
             }
           }), settings.klass.selectMonth + ' browser-default', (isOpen ? '' : 'disabled') + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' + 'title="' + settings.labelMonthSelect + '"');
         }
   
         // Materialize modified
         if (override == "short_months") if (selectedObject != null) return monthsCollection[selectedObject.month];else return monthsCollection[viewsetObject.month];
   
         // If there's a need for a month selector
         return _.node('div', monthsCollection[viewsetObject.month], settings.klass.month);
       },
           //createMonthLabel
   
   
       // Create the year label.
       // Materialize modified
       createYearLabel = function (override) {
   
         var focusedYear = viewsetObject.year,
   
   
         // If years selector is set to a literal "true", set it to 5. Otherwise
         // divide in half to get half before and half after focused year.
         numberYears = settings.selectYears === true ? 5 : ~~(settings.selectYears / 2);
   
         // If there are years to select, add a dropdown menu.
         if (numberYears) {
   
           var minYear = minLimitObject.year,
               maxYear = maxLimitObject.year,
               lowestYear = focusedYear - numberYears,
               highestYear = focusedYear + numberYears;
   
           // If the min year is greater than the lowest year, increase the highest year
           // by the difference and set the lowest year to the min year.
           if (minYear > lowestYear) {
             highestYear += minYear - lowestYear;
             lowestYear = minYear;
           }
   
           // If the max year is less than the highest year, decrease the lowest year
           // by the lower of the two: available and needed years. Then set the
           // highest year to the max year.
           if (maxYear < highestYear) {
   
             var availableYears = lowestYear - minYear,
                 neededYears = highestYear - maxYear;
   
             lowestYear -= availableYears > neededYears ? neededYears : availableYears;
             highestYear = maxYear;
           }
   
           if (settings.selectYears && override == undefined) {
             return _.node('select', _.group({
               min: lowestYear,
               max: highestYear,
               i: 1,
               node: 'option',
               item: function (loopedYear) {
                 return [
   
                 // The looped year and no classes.
                 loopedYear, 0,
   
                 // Set the value and selected index.
                 'value=' + loopedYear + (focusedYear == loopedYear ? ' selected' : '')];
               }
             }), settings.klass.selectYear + ' browser-default', (isOpen ? '' : 'disabled') + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' + 'title="' + settings.labelYearSelect + '"');
           }
         }
   
         // Materialize modified
         if (override == "raw") return _.node('div', focusedYear);
   
         // Otherwise just return the year focused
         return _.node('div', focusedYear, settings.klass.year);
       }; //createYearLabel
   
   
       // Materialize modified
       createDayLabel = function () {
         if (selectedObject != null) return selectedObject.date;else return nowObject.date;
       };
       createWeekdayLabel = function () {
         var display_day;
   
         if (selectedObject != null) display_day = selectedObject.day;else display_day = nowObject.day;
         var weekday = settings.weekdaysShort[display_day];
         return weekday;
       };
   
       // Create and return the entire calendar.
   
       return _.node(
       // Date presentation View
       'div', _.node(
       // Div for Year
       'div', createYearLabel("raw"), settings.klass.year_display) + _.node('span', createWeekdayLabel() + ', ', "picker__weekday-display") + _.node(
       // Div for short Month
       'span', createMonthLabel("short_months") + ' ', settings.klass.month_display) + _.node(
       // Div for Day
       'span', createDayLabel(), settings.klass.day_display), settings.klass.date_display) +
       // Calendar container
       _.node('div', _.node('div', _.node('div', (settings.selectYears ? createMonthLabel() + createYearLabel() : createMonthLabel() + createYearLabel()) + createMonthNav() + createMonthNav(1), settings.klass.header) + _.node('table', tableHead + _.node('tbody', _.group({
         min: 0,
         max: WEEKS_IN_CALENDAR - 1,
         i: 1,
         node: 'tr',
         item: function (rowCounter) {
   
           // If Monday is the first day and the month starts on Sunday, shift the date back a week.
           var shiftDateBy = settings.firstDay && calendar.create([viewsetObject.year, viewsetObject.month, 1]).day === 0 ? -7 : 0;
   
           return [_.group({
             min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index
             max: function () {
               return this.min + DAYS_IN_WEEK - 1;
             },
             i: 1,
             node: 'td',
             item: function (targetDate) {
   
               // Convert the time date from a relative date to a target date.
               targetDate = calendar.create([viewsetObject.year, viewsetObject.month, targetDate + (settings.firstDay ? 1 : 0)]);
   
               var isSelected = selectedObject && selectedObject.pick == targetDate.pick,
                   isHighlighted = highlightedObject && highlightedObject.pick == targetDate.pick,
                   isDisabled = disabledCollection && calendar.disabled(targetDate) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick,
                   formattedDate = _.trigger(calendar.formats.toString, calendar, [settings.format, targetDate]);
   
               return [_.node('div', targetDate.date, function (klasses) {
   
                 // Add the `infocus` or `outfocus` classes based on month in view.
                 klasses.push(viewsetObject.month == targetDate.month ? settings.klass.infocus : settings.klass.outfocus);
   
                 // Add the `today` class if needed.
                 if (nowObject.pick == targetDate.pick) {
                   klasses.push(settings.klass.now);
                 }
   
                 // Add the `selected` class if something's selected and the time matches.
                 if (isSelected) {
                   klasses.push(settings.klass.selected);
                 }
   
                 // Add the `highlighted` class if something's highlighted and the time matches.
                 if (isHighlighted) {
                   klasses.push(settings.klass.highlighted);
                 }
   
                 // Add the `disabled` class if something's disabled and the object matches.
                 if (isDisabled) {
                   klasses.push(settings.klass.disabled);
                 }
   
                 return klasses.join(' ');
               }([settings.klass.day]), 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({
                 role: 'gridcell',
                 label: formattedDate,
                 selected: isSelected && calendar.$node.val() === formattedDate ? true : null,
                 activedescendant: isHighlighted ? true : null,
                 disabled: isDisabled ? true : null
               }) + ' ' + (isDisabled ? '' : 'tabindex="0"')), '', _.ariaAttr({ role: 'presentation' })]; //endreturn
             }
           })]; //endreturn
         }
       })), settings.klass.table, 'id="' + calendar.$node[0].id + '_table' + '" ' + _.ariaAttr({
         role: 'grid',
         controls: calendar.$node[0].id,
         readonly: true
       })), settings.klass.calendar_container) // end calendar
   
       +
   
       // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”.
       _.node('div', _.node('button', settings.today, "btn-flat picker__today waves-effect", 'type=button data-pick=' + nowObject.pick + (isOpen && !calendar.disabled(nowObject) ? '' : ' disabled') + ' ' + _.ariaAttr({ controls: calendar.$node[0].id })) + _.node('button', settings.clear, "btn-flat picker__clear waves-effect", 'type=button data-clear=1' + (isOpen ? '' : ' disabled') + ' ' + _.ariaAttr({ controls: calendar.$node[0].id })) + _.node('button', settings.close, "btn-flat picker__close waves-effect", 'type=button data-close=true ' + (isOpen ? '' : ' disabled') + ' ' + _.ariaAttr({ controls: calendar.$node[0].id })), settings.klass.footer), 'picker__container__wrapper'); //endreturn
     }; //DatePicker.prototype.nodes
   
   
     /**
      * The date picker defaults.
      */
     DatePicker.defaults = function (prefix) {
   
       return {
   
         // The title label to use for the month nav buttons
         labelMonthNext: 'Next month',
         labelMonthPrev: 'Previous month',
   
         // The title label to use for the dropdown selectors
         labelMonthSelect: 'Select a month',
         labelYearSelect: 'Select a year',
   
         // Months and weekdays
         monthsFull: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
         monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
         weekdaysFull: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
         weekdaysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
   
         // Materialize modified
         weekdaysLetter: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
   
         // Today and clear
         today: 'Today',
         clear: 'Clear',
         close: 'Ok',
   
         // Picker close behavior (Prevent a change in behaviour for backwards compatibility)
         closeOnSelect: false,
   
         // The format to show on the `input` element
         format: 'd mmmm, yyyy',
   
         // Classes
         klass: {
   
           table: prefix + 'table',
   
           header: prefix + 'header',
   
           // Materialize Added klasses
           date_display: prefix + 'date-display',
           day_display: prefix + 'day-display',
           month_display: prefix + 'month-display',
           year_display: prefix + 'year-display',
           calendar_container: prefix + 'calendar-container',
           // end
   
   
           navPrev: prefix + 'nav--prev',
           navNext: prefix + 'nav--next',
           navDisabled: prefix + 'nav--disabled',
   
           month: prefix + 'month',
           year: prefix + 'year',
   
           selectMonth: prefix + 'select--month',
           selectYear: prefix + 'select--year',
   
           weekdays: prefix + 'weekday',
   
           day: prefix + 'day',
           disabled: prefix + 'day--disabled',
           selected: prefix + 'day--selected',
           highlighted: prefix + 'day--highlighted',
           now: prefix + 'day--today',
           infocus: prefix + 'day--infocus',
           outfocus: prefix + 'day--outfocus',
   
           footer: prefix + 'footer',
   
           buttonClear: prefix + 'button--clear',
           buttonToday: prefix + 'button--today',
           buttonClose: prefix + 'button--close'
         }
       };
     }(Picker.klasses().picker + '__');
   
     /**
      * Extend the picker to add the date picker.
      */
     Picker.extend('pickadate', DatePicker);
   });
   ; /*!
     * ClockPicker v0.0.7 (http://weareoutman.github.io/clockpicker/)
     * Copyright 2014 Wang Shenwei.
     * Licensed under MIT (https://github.com/weareoutman/clockpicker/blob/gh-pages/LICENSE)
     *
     * Further modified
     * Copyright 2015 Ching Yaw Hao.
     */
   
   (function () {
     var $ = window.jQuery,
         $win = $(window),
         $doc = $(document);
   
     // Can I use inline svg ?
     var svgNS = 'http://www.w3.org/2000/svg',
         svgSupported = 'SVGAngle' in window && function () {
       var supported,
           el = document.createElement('div');
       el.innerHTML = '<svg/>';
       supported = (el.firstChild && el.firstChild.namespaceURI) == svgNS;
       el.innerHTML = '';
       return supported;
     }();
   
     // Can I use transition ?
     var transitionSupported = function () {
       var style = document.createElement('div').style;
       return 'transition' in style || 'WebkitTransition' in style || 'MozTransition' in style || 'msTransition' in style || 'OTransition' in style;
     }();
   
     // Listen touch events in touch screen device, instead of mouse events in desktop.
     var touchSupported = 'ontouchstart' in window,
         mousedownEvent = 'mousedown' + (touchSupported ? ' touchstart' : ''),
         mousemoveEvent = 'mousemove.clockpicker' + (touchSupported ? ' touchmove.clockpicker' : ''),
         mouseupEvent = 'mouseup.clockpicker' + (touchSupported ? ' touchend.clockpicker' : '');
   
     // Vibrate the device if supported
     var vibrate = navigator.vibrate ? 'vibrate' : navigator.webkitVibrate ? 'webkitVibrate' : null;
   
     function createSvgElement(name) {
       return document.createElementNS(svgNS, name);
     }
   
     function leadingZero(num) {
       return (num < 10 ? '0' : '') + num;
     }
   
     // Get a unique id
     var idCounter = 0;
     function uniqueId(prefix) {
       var id = ++idCounter + '';
       return prefix ? prefix + id : id;
     }
   
     // Clock size
     var dialRadius = 135,
         outerRadius = 105,
   
     // innerRadius = 80 on 12 hour clock
     innerRadius = 80,
         tickRadius = 20,
         diameter = dialRadius * 2,
         duration = transitionSupported ? 350 : 1;
   
     // Popover template
     var tpl = ['<div class="clockpicker picker">', '<div class="picker__holder">', '<div class="picker__frame">', '<div class="picker__wrap">', '<div class="picker__box">', '<div class="picker__date-display">', '<div class="clockpicker-display">', '<div class="clockpicker-display-column">', '<span class="clockpicker-span-hours text-primary"></span>', ':', '<span class="clockpicker-span-minutes"></span>', '</div>', '<div class="clockpicker-display-column clockpicker-display-am-pm">', '<div class="clockpicker-span-am-pm"></div>', '</div>', '</div>', '</div>', '<div class="picker__container__wrapper">', '<div class="picker__calendar-container">', '<div class="clockpicker-plate">', '<div class="clockpicker-canvas"></div>', '<div class="clockpicker-dial clockpicker-hours"></div>', '<div class="clockpicker-dial clockpicker-minutes clockpicker-dial-out"></div>', '</div>', '<div class="clockpicker-am-pm-block">', '</div>', '</div>', '<div class="picker__footer">', '</div>', '</div>', '</div>', '</div>', '</div>', '</div>', '</div>'].join('');
   
     // ClockPicker
     function ClockPicker(element, options) {
       var popover = $(tpl),
           plate = popover.find('.clockpicker-plate'),
           holder = popover.find('.picker__holder'),
           hoursView = popover.find('.clockpicker-hours'),
           minutesView = popover.find('.clockpicker-minutes'),
           amPmBlock = popover.find('.clockpicker-am-pm-block'),
           isInput = element.prop('tagName') === 'INPUT',
           input = isInput ? element : element.find('input'),
           label = $("label[for=" + input.attr("id") + "]"),
           self = this;
   
       this.id = uniqueId('cp');
       this.element = element;
       this.holder = holder;
       this.options = options;
       this.isAppended = false;
       this.isShown = false;
       this.currentView = 'hours';
       this.isInput = isInput;
       this.input = input;
       this.label = label;
       this.popover = popover;
       this.plate = plate;
       this.hoursView = hoursView;
       this.minutesView = minutesView;
       this.amPmBlock = amPmBlock;
       this.spanHours = popover.find('.clockpicker-span-hours');
       this.spanMinutes = popover.find('.clockpicker-span-minutes');
       this.spanAmPm = popover.find('.clockpicker-span-am-pm');
       this.footer = popover.find('.picker__footer');
       this.amOrPm = "PM";
   
       // Setup for for 12 hour clock if option is selected
       if (options.twelvehour) {
         if (!options.ampmclickable) {
           this.spanAmPm.empty();
           $('<div id="click-am">AM</div>').appendTo(this.spanAmPm);
           $('<div id="click-pm">PM</div>').appendTo(this.spanAmPm);
         } else {
           this.spanAmPm.empty();
           $('<div id="click-am">AM</div>').on("click", function () {
             self.spanAmPm.children('#click-am').addClass("text-primary");
             self.spanAmPm.children('#click-pm').removeClass("text-primary");
             self.amOrPm = "AM";
           }).appendTo(this.spanAmPm);
           $('<div id="click-pm">PM</div>').on("click", function () {
             self.spanAmPm.children('#click-pm').addClass("text-primary");
             self.spanAmPm.children('#click-am').removeClass("text-primary");
             self.amOrPm = 'PM';
           }).appendTo(this.spanAmPm);
         }
       }
   
       // Add buttons to footer
       $('<button type="button" class="btn-flat picker__clear" tabindex="' + (options.twelvehour ? '3' : '1') + '">' + options.cleartext + '</button>').click($.proxy(this.clear, this)).appendTo(this.footer);
       $('<button type="button" class="btn-flat picker__close" tabindex="' + (options.twelvehour ? '3' : '1') + '">' + options.canceltext + '</button>').click($.proxy(this.hide, this)).appendTo(this.footer);
       $('<button type="button" class="btn-flat picker__close" tabindex="' + (options.twelvehour ? '3' : '1') + '">' + options.donetext + '</button>').click($.proxy(this.done, this)).appendTo(this.footer);
   
       this.spanHours.click($.proxy(this.toggleView, this, 'hours'));
       this.spanMinutes.click($.proxy(this.toggleView, this, 'minutes'));
   
       // Show or toggle
       input.on('focus.clockpicker click.clockpicker', $.proxy(this.show, this));
   
       // Build ticks
       var tickTpl = $('<div class="clockpicker-tick"></div>'),
           i,
           tick,
           radian,
           radius;
   
       // Hours view
       if (options.twelvehour) {
         for (i = 1; i < 13; i += 1) {
           tick = tickTpl.clone();
           radian = i / 6 * Math.PI;
           radius = outerRadius;
           tick.css({
             left: dialRadius + Math.sin(radian) * radius - tickRadius,
             top: dialRadius - Math.cos(radian) * radius - tickRadius
           });
           tick.html(i === 0 ? '00' : i);
           hoursView.append(tick);
           tick.on(mousedownEvent, mousedown);
         }
       } else {
         for (i = 0; i < 24; i += 1) {
           tick = tickTpl.clone();
           radian = i / 6 * Math.PI;
           var inner = i > 0 && i < 13;
           radius = inner ? innerRadius : outerRadius;
           tick.css({
             left: dialRadius + Math.sin(radian) * radius - tickRadius,
             top: dialRadius - Math.cos(radian) * radius - tickRadius
           });
           tick.html(i === 0 ? '00' : i);
           hoursView.append(tick);
           tick.on(mousedownEvent, mousedown);
         }
       }
   
       // Minutes view
       for (i = 0; i < 60; i += 5) {
         tick = tickTpl.clone();
         radian = i / 30 * Math.PI;
         tick.css({
           left: dialRadius + Math.sin(radian) * outerRadius - tickRadius,
           top: dialRadius - Math.cos(radian) * outerRadius - tickRadius
         });
         tick.html(leadingZero(i));
         minutesView.append(tick);
         tick.on(mousedownEvent, mousedown);
       }
   
       // Clicking on minutes view space
       plate.on(mousedownEvent, function (e) {
         if ($(e.target).closest('.clockpicker-tick').length === 0) {
           mousedown(e, true);
         }
       });
   
       // Mousedown or touchstart
       function mousedown(e, space) {
         var offset = plate.offset(),
             isTouch = /^touch/.test(e.type),
             x0 = offset.left + dialRadius,
             y0 = offset.top + dialRadius,
             dx = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0,
             dy = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0,
             z = Math.sqrt(dx * dx + dy * dy),
             moved = false;
   
         // When clicking on minutes view space, check the mouse position
         if (space && (z < outerRadius - tickRadius || z > outerRadius + tickRadius)) {
           return;
         }
         e.preventDefault();
   
         // Set cursor style of body after 200ms
         var movingTimer = setTimeout(function () {
           self.popover.addClass('clockpicker-moving');
         }, 200);
   
         // Clock
         self.setHand(dx, dy, !space, true);
   
         // Mousemove on document
         $doc.off(mousemoveEvent).on(mousemoveEvent, function (e) {
           e.preventDefault();
           var isTouch = /^touch/.test(e.type),
               x = (isTouch ? e.originalEvent.touches[0] : e).pageX - x0,
               y = (isTouch ? e.originalEvent.touches[0] : e).pageY - y0;
           if (!moved && x === dx && y === dy) {
             // Clicking in chrome on windows will trigger a mousemove event
             return;
           }
           moved = true;
           self.setHand(x, y, false, true);
         });
   
         // Mouseup on document
         $doc.off(mouseupEvent).on(mouseupEvent, function (e) {
           $doc.off(mouseupEvent);
           e.preventDefault();
           var isTouch = /^touch/.test(e.type),
               x = (isTouch ? e.originalEvent.changedTouches[0] : e).pageX - x0,
               y = (isTouch ? e.originalEvent.changedTouches[0] : e).pageY - y0;
           if ((space || moved) && x === dx && y === dy) {
             self.setHand(x, y);
           }
   
           if (self.currentView === 'hours') {
             self.toggleView('minutes', duration / 2);
           } else if (options.autoclose) {
             self.minutesView.addClass('clockpicker-dial-out');
             setTimeout(function () {
               self.done();
             }, duration / 2);
           }
           plate.prepend(canvas);
   
           // Reset cursor style of body
           clearTimeout(movingTimer);
           self.popover.removeClass('clockpicker-moving');
   
           // Unbind mousemove event
           $doc.off(mousemoveEvent);
         });
       }
   
       if (svgSupported) {
         // Draw clock hands and others
         var canvas = popover.find('.clockpicker-canvas'),
             svg = createSvgElement('svg');
         svg.setAttribute('class', 'clockpicker-svg');
         svg.setAttribute('width', diameter);
         svg.setAttribute('height', diameter);
         var g = createSvgElement('g');
         g.setAttribute('transform', 'translate(' + dialRadius + ',' + dialRadius + ')');
         var bearing = createSvgElement('circle');
         bearing.setAttribute('class', 'clockpicker-canvas-bearing');
         bearing.setAttribute('cx', 0);
         bearing.setAttribute('cy', 0);
         bearing.setAttribute('r', 4);
         var hand = createSvgElement('line');
         hand.setAttribute('x1', 0);
         hand.setAttribute('y1', 0);
         var bg = createSvgElement('circle');
         bg.setAttribute('class', 'clockpicker-canvas-bg');
         bg.setAttribute('r', tickRadius);
         g.appendChild(hand);
         g.appendChild(bg);
         g.appendChild(bearing);
         svg.appendChild(g);
         canvas.append(svg);
   
         this.hand = hand;
         this.bg = bg;
         this.bearing = bearing;
         this.g = g;
         this.canvas = canvas;
       }
   
       raiseCallback(this.options.init);
     }
   
     function raiseCallback(callbackFunction) {
       if (callbackFunction && typeof callbackFunction === "function") callbackFunction();
     }
   
     // Default options
     ClockPicker.DEFAULTS = {
       'default': '', // default time, 'now' or '13:14' e.g.
       fromnow: 0, // set default time to * milliseconds from now (using with default = 'now')
       donetext: 'Ok', // done button text
       cleartext: 'Clear',
       canceltext: 'Cancel',
       autoclose: false, // auto close when minute is selected
       ampmclickable: true, // set am/pm button on itself
       darktheme: false, // set to dark theme
       twelvehour: true, // change to 12 hour AM/PM clock from 24 hour
       vibrate: true // vibrate the device when dragging clock hand
     };
   
     // Show or hide popover
     ClockPicker.prototype.toggle = function () {
       this[this.isShown ? 'hide' : 'show']();
     };
   
     // Set popover position
     ClockPicker.prototype.locate = function () {
       var element = this.element,
           popover = this.popover,
           offset = element.offset(),
           width = element.outerWidth(),
           height = element.outerHeight(),
           align = this.options.align,
           self = this;
   
       popover.show();
     };
   
     // Show popover
     ClockPicker.prototype.show = function (e) {
       // Not show again
       if (this.isShown) {
         return;
       }
       raiseCallback(this.options.beforeShow);
       $(':input').each(function () {
         $(this).attr('tabindex', -1);
       });
       var self = this;
       // Initialize
       this.input.blur();
       this.popover.addClass('picker--opened');
       this.input.addClass('picker__input picker__input--active');
       $(document.body).css('overflow', 'hidden');
       // Get the time
       var value = ((this.input.prop('value') || this.options['default'] || '') + '').split(':');
       if (this.options.twelvehour && !(typeof value[1] === 'undefined')) {
         if (value[1].indexOf("AM") > 0) {
           this.amOrPm = 'AM';
         } else {
           this.amOrPm = 'PM';
         }
         value[1] = value[1].replace("AM", "").replace("PM", "");
       }
       if (value[0] === 'now') {
         var now = new Date(+new Date() + this.options.fromnow);
         value = [now.getHours(), now.getMinutes()];
         if (this.options.twelvehour) {
           this.amOrPm = value[0] >= 12 && value[0] < 24 ? 'PM' : 'AM';
         }
       }
       this.hours = +value[0] || 0;
       this.minutes = +value[1] || 0;
       this.spanHours.html(this.hours);
       this.spanMinutes.html(leadingZero(this.minutes));
       if (!this.isAppended) {
         // Append popover to body
         this.popover.insertAfter(this.input);
         if (this.options.twelvehour) {
           if (this.amOrPm === 'PM') {
             this.spanAmPm.children('#click-pm').addClass("text-primary");
             this.spanAmPm.children('#click-am').removeClass("text-primary");
           } else {
             this.spanAmPm.children('#click-am').addClass("text-primary");
             this.spanAmPm.children('#click-pm').removeClass("text-primary");
           }
         }
         // Reset position when resize
         $win.on('resize.clockpicker' + this.id, function () {
           if (self.isShown) {
             self.locate();
           }
         });
         this.isAppended = true;
       }
       // Toggle to hours view
       this.toggleView('hours');
       // Set position
       this.locate();
       this.isShown = true;
       // Hide when clicking or tabbing on any element except the clock and input
       $doc.on('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id, function (e) {
         var target = $(e.target);
         if (target.closest(self.popover.find('.picker__wrap')).length === 0 && target.closest(self.input).length === 0) {
           self.hide();
         }
       });
       // Hide when ESC is pressed
       $doc.on('keyup.clockpicker.' + this.id, function (e) {
         if (e.keyCode === 27) {
           self.hide();
         }
       });
       raiseCallback(this.options.afterShow);
     };
     // Hide popover
     ClockPicker.prototype.hide = function () {
       raiseCallback(this.options.beforeHide);
       this.input.removeClass('picker__input picker__input--active');
       this.popover.removeClass('picker--opened');
       $(document.body).css('overflow', 'visible');
       this.isShown = false;
       $(':input').each(function (index) {
         $(this).attr('tabindex', index + 1);
       });
       // Unbinding events on document
       $doc.off('click.clockpicker.' + this.id + ' focusin.clockpicker.' + this.id);
       $doc.off('keyup.clockpicker.' + this.id);
       this.popover.hide();
       raiseCallback(this.options.afterHide);
     };
     // Toggle to hours or minutes view
     ClockPicker.prototype.toggleView = function (view, delay) {
       var raiseAfterHourSelect = false;
       if (view === 'minutes' && $(this.hoursView).css("visibility") === "visible") {
         raiseCallback(this.options.beforeHourSelect);
         raiseAfterHourSelect = true;
       }
       var isHours = view === 'hours',
           nextView = isHours ? this.hoursView : this.minutesView,
           hideView = isHours ? this.minutesView : this.hoursView;
       this.currentView = view;
   
       this.spanHours.toggleClass('text-primary', isHours);
       this.spanMinutes.toggleClass('text-primary', !isHours);
   
       // Let's make transitions
       hideView.addClass('clockpicker-dial-out');
       nextView.css('visibility', 'visible').removeClass('clockpicker-dial-out');
   
       // Reset clock hand
       this.resetClock(delay);
   
       // After transitions ended
       clearTimeout(this.toggleViewTimer);
       this.toggleViewTimer = setTimeout(function () {
         hideView.css('visibility', 'hidden');
       }, duration);
   
       if (raiseAfterHourSelect) {
         raiseCallback(this.options.afterHourSelect);
       }
     };
   
     // Reset clock hand
     ClockPicker.prototype.resetClock = function (delay) {
       var view = this.currentView,
           value = this[view],
           isHours = view === 'hours',
           unit = Math.PI / (isHours ? 6 : 30),
           radian = value * unit,
           radius = isHours && value > 0 && value < 13 ? innerRadius : outerRadius,
           x = Math.sin(radian) * radius,
           y = -Math.cos(radian) * radius,
           self = this;
   
       if (svgSupported && delay) {
         self.canvas.addClass('clockpicker-canvas-out');
         setTimeout(function () {
           self.canvas.removeClass('clockpicker-canvas-out');
           self.setHand(x, y);
         }, delay);
       } else this.setHand(x, y);
     };
   
     // Set clock hand to (x, y)
     ClockPicker.prototype.setHand = function (x, y, roundBy5, dragging) {
       var radian = Math.atan2(x, -y),
           isHours = this.currentView === 'hours',
           unit = Math.PI / (isHours || roundBy5 ? 6 : 30),
           z = Math.sqrt(x * x + y * y),
           options = this.options,
           inner = isHours && z < (outerRadius + innerRadius) / 2,
           radius = inner ? innerRadius : outerRadius,
           value;
   
       if (options.twelvehour) {
         radius = outerRadius;
       }
   
       // Radian should in range [0, 2PI]
       if (radian < 0) {
         radian = Math.PI * 2 + radian;
       }
   
       // Get the round value
       value = Math.round(radian / unit);
   
       // Get the round radian
       radian = value * unit;
   
       // Correct the hours or minutes
       if (options.twelvehour) {
         if (isHours) {
           if (value === 0) value = 12;
         } else {
           if (roundBy5) value *= 5;
           if (value === 60) value = 0;
         }
       } else {
         if (isHours) {
           if (value === 12) value = 0;
           value = inner ? value === 0 ? 12 : value : value === 0 ? 0 : value + 12;
         } else {
           if (roundBy5) value *= 5;
           if (value === 60) value = 0;
         }
       }
   
       // Once hours or minutes changed, vibrate the device
       if (this[this.currentView] !== value) {
         if (vibrate && this.options.vibrate) {
           // Do not vibrate too frequently
           if (!this.vibrateTimer) {
             navigator[vibrate](10);
             this.vibrateTimer = setTimeout($.proxy(function () {
               this.vibrateTimer = null;
             }, this), 100);
           }
         }
       }
   
       this[this.currentView] = value;
       if (isHours) {
         this['spanHours'].html(value);
       } else {
         this['spanMinutes'].html(leadingZero(value));
       }
   
       // If svg is not supported, just add an active class to the tick
       if (!svgSupported) {
         this[isHours ? 'hoursView' : 'minutesView'].find('.clockpicker-tick').each(function () {
           var tick = $(this);
           tick.toggleClass('active', value === +tick.html());
         });
         return;
       }
   
       // Set clock hand and others' position
       var cx1 = Math.sin(radian) * (radius - tickRadius),
           cy1 = -Math.cos(radian) * (radius - tickRadius),
           cx2 = Math.sin(radian) * radius,
           cy2 = -Math.cos(radian) * radius;
       this.hand.setAttribute('x2', cx1);
       this.hand.setAttribute('y2', cy1);
       this.bg.setAttribute('cx', cx2);
       this.bg.setAttribute('cy', cy2);
     };
   
     // Hours and minutes are selected
     ClockPicker.prototype.done = function () {
       raiseCallback(this.options.beforeDone);
       this.hide();
       this.label.addClass('active');
   
       var last = this.input.prop('value'),
           value = leadingZero(this.hours) + ':' + leadingZero(this.minutes);
       if (this.options.twelvehour) {
         value = value + this.amOrPm;
       }
   
       this.input.prop('value', value);
       if (value !== last) {
         this.input.triggerHandler('change');
         if (!this.isInput) {
           this.element.trigger('change');
         }
       }
   
       if (this.options.autoclose) this.input.trigger('blur');
   
       raiseCallback(this.options.afterDone);
     };
   
     // Clear input field
     ClockPicker.prototype.clear = function () {
       this.hide();
       this.label.removeClass('active');
   
       var last = this.input.prop('value'),
           value = '';
   
       this.input.prop('value', value);
       if (value !== last) {
         this.input.triggerHandler('change');
         if (!this.isInput) {
           this.element.trigger('change');
         }
       }
   
       if (this.options.autoclose) {
         this.input.trigger('blur');
       }
     };
   
     // Remove clockpicker from input
     ClockPicker.prototype.remove = function () {
       this.element.removeData('clockpicker');
       this.input.off('focus.clockpicker click.clockpicker');
       if (this.isShown) {
         this.hide();
       }
       if (this.isAppended) {
         $win.off('resize.clockpicker' + this.id);
         this.popover.remove();
       }
     };
   
     // Extends $.fn.clockpicker
     $.fn.pickatime = function (option) {
       var args = Array.prototype.slice.call(arguments, 1);
       return this.each(function () {
         var $this = $(this),
             data = $this.data('clockpicker');
         if (!data) {
           var options = $.extend({}, ClockPicker.DEFAULTS, $this.data(), typeof option == 'object' && option);
           $this.data('clockpicker', new ClockPicker($this, options));
         } else {
           // Manual operatsions. show, hide, remove, e.g.
           if (typeof data[option] === 'function') {
             data[option].apply(data, args);
           }
         }
       });
     };
   })();
   ;(function ($) {
   
     $.fn.characterCounter = function () {
       return this.each(function () {
         var $input = $(this);
         var $counterElement = $input.parent().find('span[class="character-counter"]');
   
         // character counter has already been added appended to the parent container
         if ($counterElement.length) {
           return;
         }
   
         var itHasLengthAttribute = $input.attr('data-length') !== undefined;
   
         if (itHasLengthAttribute) {
           $input.on('input', updateCounter);
           $input.on('focus', updateCounter);
           $input.on('blur', removeCounterElement);
   
           addCounterElement($input);
         }
       });
     };
   
     function updateCounter() {
       var maxLength = +$(this).attr('data-length'),
           actualLength = +$(this).val().length,
           isValidLength = actualLength <= maxLength;
   
       $(this).parent().find('span[class="character-counter"]').html(actualLength + '/' + maxLength);
   
       addInputStyle(isValidLength, $(this));
     }
   
     function addCounterElement($input) {
       var $counterElement = $input.parent().find('span[class="character-counter"]');
   
       if ($counterElement.length) {
         return;
       }
   
       $counterElement = $('<span/>').addClass('character-counter').css('float', 'right').css('font-size', '12px').css('height', 1);
   
       $input.parent().append($counterElement);
     }
   
     function removeCounterElement() {
       $(this).parent().find('span[class="character-counter"]').html('');
     }
   
     function addInputStyle(isValidLength, $input) {
       var inputHasInvalidClass = $input.hasClass('invalid');
       if (isValidLength && inputHasInvalidClass) {
         $input.removeClass('invalid');
       } else if (!isValidLength && !inputHasInvalidClass) {
         $input.removeClass('valid');
         $input.addClass('invalid');
       }
     }
   
     $(document).ready(function () {
       $('input, textarea').characterCounter();
     });
   })(jQuery);
   ;(function ($) {
   
     var methods = {
   
       init: function (options) {
         var defaults = {
           duration: 200, // ms
           dist: -100, // zoom scale TODO: make this more intuitive as an option
           shift: 0, // spacing for center image
           padding: 0, // Padding between non center items
           fullWidth: false, // Change to full width styles
           indicators: false, // Toggle indicators
           noWrap: false, // Don't wrap around and cycle through items.
           onCycleTo: null // Callback for when a new slide is cycled to.
         };
         options = $.extend(defaults, options);
         var namespace = Materialize.objectSelectorString($(this));
   
         return this.each(function (i) {
   
           var images, item_width, item_height, offset, center, pressed, dim, count, reference, referenceY, amplitude, target, velocity, scrolling, xform, frame, timestamp, ticker, dragged, vertical_dragged;
           var $indicators = $('<ul class="indicators"></ul>');
           var scrollingTimeout = null;
           var oneTimeCallback = null;
   
           // Initialize
           var view = $(this);
           var hasMultipleSlides = view.find('.carousel-item').length > 1;
           var showIndicators = (view.attr('data-indicators') || options.indicators) && hasMultipleSlides;
           var noWrap = view.attr('data-no-wrap') || options.noWrap || !hasMultipleSlides;
           var uniqueNamespace = view.attr('data-namespace') || namespace + i;
           view.attr('data-namespace', uniqueNamespace);
   
           // Options
           var setCarouselHeight = function (imageOnly) {
             var firstSlide = view.find('.carousel-item.active').length ? view.find('.carousel-item.active').first() : view.find('.carousel-item').first();
             var firstImage = firstSlide.find('img').first();
             if (firstImage.length) {
               if (firstImage[0].complete) {
                 // If image won't trigger the load event
                 var imageHeight = firstImage.height();
                 if (imageHeight > 0) {
                   view.css('height', firstImage.height());
                 } else {
                   // If image still has no height, use the natural dimensions to calculate
                   var naturalWidth = firstImage[0].naturalWidth;
                   var naturalHeight = firstImage[0].naturalHeight;
                   var adjustedHeight = view.width() / naturalWidth * naturalHeight;
                   view.css('height', adjustedHeight);
                 }
               } else {
                 // Get height when image is loaded normally
                 firstImage.on('load', function () {
                   view.css('height', $(this).height());
                 });
               }
             } else if (!imageOnly) {
               var slideHeight = firstSlide.height();
               view.css('height', slideHeight);
             }
           };
   
           if (options.fullWidth) {
             options.dist = 0;
             setCarouselHeight();
   
             // Offset fixed items when indicators.
             if (showIndicators) {
               view.find('.carousel-fixed-item').addClass('with-indicators');
             }
           }
   
           // Don't double initialize.
           if (view.hasClass('initialized')) {
             // Recalculate variables
             $(window).trigger('resize');
   
             // Redraw carousel.
             view.trigger('carouselNext', [0.000001]);
             return true;
           }
   
           view.addClass('initialized');
           pressed = false;
           offset = target = 0;
           images = [];
           item_width = view.find('.carousel-item').first().innerWidth();
           item_height = view.find('.carousel-item').first().innerHeight();
           dim = item_width * 2 + options.padding;
   
           view.find('.carousel-item').each(function (i) {
             images.push($(this)[0]);
             if (showIndicators) {
               var $indicator = $('<li class="indicator-item"></li>');
   
               // Add active to first by default.
               if (i === 0) {
                 $indicator.addClass('active');
               }
   
               // Handle clicks on indicators.
               $indicator.click(function (e) {
                 e.stopPropagation();
   
                 var index = $(this).index();
                 cycleTo(index);
               });
               $indicators.append($indicator);
             }
           });
   
           if (showIndicators) {
             view.append($indicators);
           }
           count = images.length;
   
           function setupEvents() {
             if (typeof window.ontouchstart !== 'undefined') {
               view.on('touchstart.carousel', tap);
               view.on('touchmove.carousel', drag);
               view.on('touchend.carousel', release);
             }
             view.on('mousedown.carousel', tap);
             view.on('mousemove.carousel', drag);
             view.on('mouseup.carousel', release);
             view.on('mouseleave.carousel', release);
             view.on('click.carousel', click);
           }
   
           function xpos(e) {
             // touch event
             if (e.targetTouches && e.targetTouches.length >= 1) {
               return e.targetTouches[0].clientX;
             }
   
             // mouse event
             return e.clientX;
           }
   
           function ypos(e) {
             // touch event
             if (e.targetTouches && e.targetTouches.length >= 1) {
               return e.targetTouches[0].clientY;
             }
   
             // mouse event
             return e.clientY;
           }
   
           function wrap(x) {
             return x >= count ? x % count : x < 0 ? wrap(count + x % count) : x;
           }
   
           function scroll(x) {
             // Track scrolling state
             scrolling = true;
             if (!view.hasClass('scrolling')) {
               view.addClass('scrolling');
             }
             if (scrollingTimeout != null) {
               window.clearTimeout(scrollingTimeout);
             }
             scrollingTimeout = window.setTimeout(function () {
               scrolling = false;
               view.removeClass('scrolling');
             }, options.duration);
   
             // Start actual scroll
             var i, half, delta, dir, tween, el, alignment, xTranslation;
             var lastCenter = center;
   
             offset = typeof x === 'number' ? x : offset;
             center = Math.floor((offset + dim / 2) / dim);
             delta = offset - center * dim;
             dir = delta < 0 ? 1 : -1;
             tween = -dir * delta * 2 / dim;
             half = count >> 1;
   
             if (!options.fullWidth) {
               alignment = 'translateX(' + (view[0].clientWidth - item_width) / 2 + 'px) ';
               alignment += 'translateY(' + (view[0].clientHeight - item_height) / 2 + 'px)';
             } else {
               alignment = 'translateX(0)';
             }
   
             // Set indicator active
             if (showIndicators) {
               var diff = center % count;
               var activeIndicator = $indicators.find('.indicator-item.active');
               if (activeIndicator.index() !== diff) {
                 activeIndicator.removeClass('active');
                 $indicators.find('.indicator-item').eq(diff).addClass('active');
               }
             }
   
             // center
             // Don't show wrapped items.
             if (!noWrap || center >= 0 && center < count) {
               el = images[wrap(center)];
   
               // Add active class to center item.
               if (!$(el).hasClass('active')) {
                 view.find('.carousel-item').removeClass('active');
                 $(el).addClass('active');
               }
               el.style[xform] = alignment + ' translateX(' + -delta / 2 + 'px)' + ' translateX(' + dir * options.shift * tween * i + 'px)' + ' translateZ(' + options.dist * tween + 'px)';
               el.style.zIndex = 0;
               if (options.fullWidth) {
                 tweenedOpacity = 1;
               } else {
                 tweenedOpacity = 1 - 0.2 * tween;
               }
               el.style.opacity = tweenedOpacity;
               el.style.display = 'block';
             }
   
             for (i = 1; i <= half; ++i) {
               // right side
               if (options.fullWidth) {
                 zTranslation = options.dist;
                 tweenedOpacity = i === half && delta < 0 ? 1 - tween : 1;
               } else {
                 zTranslation = options.dist * (i * 2 + tween * dir);
                 tweenedOpacity = 1 - 0.2 * (i * 2 + tween * dir);
               }
               // Don't show wrapped items.
               if (!noWrap || center + i < count) {
                 el = images[wrap(center + i)];
                 el.style[xform] = alignment + ' translateX(' + (options.shift + (dim * i - delta) / 2) + 'px)' + ' translateZ(' + zTranslation + 'px)';
                 el.style.zIndex = -i;
                 el.style.opacity = tweenedOpacity;
                 el.style.display = 'block';
               }
   
               // left side
               if (options.fullWidth) {
                 zTranslation = options.dist;
                 tweenedOpacity = i === half && delta > 0 ? 1 - tween : 1;
               } else {
                 zTranslation = options.dist * (i * 2 - tween * dir);
                 tweenedOpacity = 1 - 0.2 * (i * 2 - tween * dir);
               }
               // Don't show wrapped items.
               if (!noWrap || center - i >= 0) {
                 el = images[wrap(center - i)];
                 el.style[xform] = alignment + ' translateX(' + (-options.shift + (-dim * i - delta) / 2) + 'px)' + ' translateZ(' + zTranslation + 'px)';
                 el.style.zIndex = -i;
                 el.style.opacity = tweenedOpacity;
                 el.style.display = 'block';
               }
             }
   
             // center
             // Don't show wrapped items.
             if (!noWrap || center >= 0 && center < count) {
               el = images[wrap(center)];
               el.style[xform] = alignment + ' translateX(' + -delta / 2 + 'px)' + ' translateX(' + dir * options.shift * tween + 'px)' + ' translateZ(' + options.dist * tween + 'px)';
               el.style.zIndex = 0;
               if (options.fullWidth) {
                 tweenedOpacity = 1;
               } else {
                 tweenedOpacity = 1 - 0.2 * tween;
               }
               el.style.opacity = tweenedOpacity;
               el.style.display = 'block';
             }
   
             // onCycleTo callback
             if (lastCenter !== center && typeof options.onCycleTo === "function") {
               var $curr_item = view.find('.carousel-item').eq(wrap(center));
               options.onCycleTo.call(this, $curr_item, dragged);
             }
   
             // One time callback
             if (typeof oneTimeCallback === "function") {
               oneTimeCallback.call(this, $curr_item, dragged);
               oneTimeCallback = null;
             }
           }
   
           function track() {
             var now, elapsed, delta, v;
   
             now = Date.now();
             elapsed = now - timestamp;
             timestamp = now;
             delta = offset - frame;
             frame = offset;
   
             v = 1000 * delta / (1 + elapsed);
             velocity = 0.8 * v + 0.2 * velocity;
           }
   
           function autoScroll() {
             var elapsed, delta;
   
             if (amplitude) {
               elapsed = Date.now() - timestamp;
               delta = amplitude * Math.exp(-elapsed / options.duration);
               if (delta > 2 || delta < -2) {
                 scroll(target - delta);
                 requestAnimationFrame(autoScroll);
               } else {
                 scroll(target);
               }
             }
           }
   
           function click(e) {
             // Disable clicks if carousel was dragged.
             if (dragged) {
               e.preventDefault();
               e.stopPropagation();
               return false;
             } else if (!options.fullWidth) {
               var clickedIndex = $(e.target).closest('.carousel-item').index();
               var diff = wrap(center) - clickedIndex;
   
               // Disable clicks if carousel was shifted by click
               if (diff !== 0) {
                 e.preventDefault();
                 e.stopPropagation();
               }
               cycleTo(clickedIndex);
             }
           }
   
           function cycleTo(n) {
             var diff = center % count - n;
   
             // Account for wraparound.
             if (!noWrap) {
               if (diff < 0) {
                 if (Math.abs(diff + count) < Math.abs(diff)) {
                   diff += count;
                 }
               } else if (diff > 0) {
                 if (Math.abs(diff - count) < diff) {
                   diff -= count;
                 }
               }
             }
   
             // Call prev or next accordingly.
             if (diff < 0) {
               view.trigger('carouselNext', [Math.abs(diff)]);
             } else if (diff > 0) {
               view.trigger('carouselPrev', [diff]);
             }
           }
   
           function tap(e) {
             // Fixes firefox draggable image bug
             if (e.type === 'mousedown' && $(e.target).is('img')) {
               e.preventDefault();
             }
             pressed = true;
             dragged = false;
             vertical_dragged = false;
             reference = xpos(e);
             referenceY = ypos(e);
   
             velocity = amplitude = 0;
             frame = offset;
             timestamp = Date.now();
             clearInterval(ticker);
             ticker = setInterval(track, 100);
           }
   
           function drag(e) {
             var x, delta, deltaY;
             if (pressed) {
               x = xpos(e);
               y = ypos(e);
               delta = reference - x;
               deltaY = Math.abs(referenceY - y);
               if (deltaY < 30 && !vertical_dragged) {
                 // If vertical scrolling don't allow dragging.
                 if (delta > 2 || delta < -2) {
                   dragged = true;
                   reference = x;
                   scroll(offset + delta);
                 }
               } else if (dragged) {
                 // If dragging don't allow vertical scroll.
                 e.preventDefault();
                 e.stopPropagation();
                 return false;
               } else {
                 // Vertical scrolling.
                 vertical_dragged = true;
               }
             }
   
             if (dragged) {
               // If dragging don't allow vertical scroll.
               e.preventDefault();
               e.stopPropagation();
               return false;
             }
           }
   
           function release(e) {
             if (pressed) {
               pressed = false;
             } else {
               return;
             }
   
             clearInterval(ticker);
             target = offset;
             if (velocity > 10 || velocity < -10) {
               amplitude = 0.9 * velocity;
               target = offset + amplitude;
             }
             target = Math.round(target / dim) * dim;
   
             // No wrap of items.
             if (noWrap) {
               if (target >= dim * (count - 1)) {
                 target = dim * (count - 1);
               } else if (target < 0) {
                 target = 0;
               }
             }
             amplitude = target - offset;
             timestamp = Date.now();
             requestAnimationFrame(autoScroll);
   
             if (dragged) {
               e.preventDefault();
               e.stopPropagation();
             }
             return false;
           }
   
           xform = 'transform';
           ['webkit', 'Moz', 'O', 'ms'].every(function (prefix) {
             var e = prefix + 'Transform';
             if (typeof document.body.style[e] !== 'undefined') {
               xform = e;
               return false;
             }
             return true;
           });
   
           var throttledResize = Materialize.throttle(function () {
             if (options.fullWidth) {
               item_width = view.find('.carousel-item').first().innerWidth();
               var imageHeight = view.find('.carousel-item.active').height();
               dim = item_width * 2 + options.padding;
               offset = center * 2 * item_width;
               target = offset;
               setCarouselHeight(true);
             } else {
               scroll();
             }
           }, 200);
           $(window).off('resize.carousel-' + uniqueNamespace).on('resize.carousel-' + uniqueNamespace, throttledResize);
   
           setupEvents();
           scroll(offset);
   
           $(this).on('carouselNext', function (e, n, callback) {
             if (n === undefined) {
               n = 1;
             }
             if (typeof callback === "function") {
               oneTimeCallback = callback;
             }
   
             target = dim * Math.round(offset / dim) + dim * n;
             if (offset !== target) {
               amplitude = target - offset;
               timestamp = Date.now();
               requestAnimationFrame(autoScroll);
             }
           });
   
           $(this).on('carouselPrev', function (e, n, callback) {
             if (n === undefined) {
               n = 1;
             }
             if (typeof callback === "function") {
               oneTimeCallback = callback;
             }
   
             target = dim * Math.round(offset / dim) - dim * n;
             if (offset !== target) {
               amplitude = target - offset;
               timestamp = Date.now();
               requestAnimationFrame(autoScroll);
             }
           });
   
           $(this).on('carouselSet', function (e, n, callback) {
             if (n === undefined) {
               n = 0;
             }
             if (typeof callback === "function") {
               oneTimeCallback = callback;
             }
   
             cycleTo(n);
           });
         });
       },
       next: function (n, callback) {
         $(this).trigger('carouselNext', [n, callback]);
       },
       prev: function (n, callback) {
         $(this).trigger('carouselPrev', [n, callback]);
       },
       set: function (n, callback) {
         $(this).trigger('carouselSet', [n, callback]);
       },
       destroy: function () {
         var uniqueNamespace = $(this).attr('data-namespace');
         $(this).removeAttr('data-namespace');
         $(this).removeClass('initialized');
         $(this).find('.indicators').remove();
   
         // Remove event handlers
         $(this).off('carouselNext carouselPrev carouselSet');
         $(window).off('resize.carousel-' + uniqueNamespace);
         if (typeof window.ontouchstart !== 'undefined') {
           $(this).off('touchstart.carousel touchmove.carousel touchend.carousel');
         }
         $(this).off('mousedown.carousel mousemove.carousel mouseup.carousel mouseleave.carousel click.carousel');
       }
     };
   
     $.fn.carousel = function (methodOrOptions) {
       if (methods[methodOrOptions]) {
         return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
       } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
         // Default to "init"
         return methods.init.apply(this, arguments);
       } else {
         $.error('Method ' + methodOrOptions + ' does not exist on jQuery.carousel');
       }
     }; // Plugin end
   })(jQuery);
   ;(function ($) {
   
     var methods = {
       init: function (options) {
         return this.each(function () {
           var origin = $('#' + $(this).attr('data-activates'));
           var screen = $('body');
   
           // Creating tap target
           var tapTargetEl = $(this);
           var tapTargetWrapper = tapTargetEl.parent('.tap-target-wrapper');
           var tapTargetWave = tapTargetWrapper.find('.tap-target-wave');
           var tapTargetOriginEl = tapTargetWrapper.find('.tap-target-origin');
           var tapTargetContentEl = tapTargetEl.find('.tap-target-content');
   
           // Creating wrapper
           if (!tapTargetWrapper.length) {
             tapTargetWrapper = tapTargetEl.wrap($('<div class="tap-target-wrapper"></div>')).parent();
           }
   
           // Creating content
           if (!tapTargetContentEl.length) {
             tapTargetContentEl = $('<div class="tap-target-content"></div>');
             tapTargetEl.append(tapTargetContentEl);
           }
   
           // Creating foreground wave
           if (!tapTargetWave.length) {
             tapTargetWave = $('<div class="tap-target-wave"></div>');
   
             // Creating origin
             if (!tapTargetOriginEl.length) {
               tapTargetOriginEl = origin.clone(true, true);
               tapTargetOriginEl.addClass('tap-target-origin');
               tapTargetOriginEl.removeAttr('id');
               tapTargetOriginEl.removeAttr('style');
               tapTargetWave.append(tapTargetOriginEl);
             }
   
             tapTargetWrapper.append(tapTargetWave);
           }
   
           // Open
           var openTapTarget = function () {
             if (tapTargetWrapper.is('.open')) {
               return;
             }
   
             // Adding open class
             tapTargetWrapper.addClass('open');
   
             setTimeout(function () {
               tapTargetOriginEl.off('click.tapTarget').on('click.tapTarget', function (e) {
                 closeTapTarget();
                 tapTargetOriginEl.off('click.tapTarget');
               });
   
               $(document).off('click.tapTarget').on('click.tapTarget', function (e) {
                 closeTapTarget();
                 $(document).off('click.tapTarget');
               });
   
               var throttledCalc = Materialize.throttle(function () {
                 calculateTapTarget();
               }, 200);
               $(window).off('resize.tapTarget').on('resize.tapTarget', throttledCalc);
             }, 0);
           };
   
           // Close
           var closeTapTarget = function () {
             if (!tapTargetWrapper.is('.open')) {
               return;
             }
   
             tapTargetWrapper.removeClass('open');
             tapTargetOriginEl.off('click.tapTarget');
             $(document).off('click.tapTarget');
             $(window).off('resize.tapTarget');
           };
   
           // Pre calculate
           var calculateTapTarget = function () {
             // Element or parent is fixed position?
             var isFixed = origin.css('position') === 'fixed';
             if (!isFixed) {
               var parents = origin.parents();
               for (var i = 0; i < parents.length; i++) {
                 isFixed = $(parents[i]).css('position') == 'fixed';
                 if (isFixed) {
                   break;
                 }
               }
             }
   
             // Calculating origin
             var originWidth = origin.outerWidth();
             var originHeight = origin.outerHeight();
             var originTop = isFixed ? origin.offset().top - $(document).scrollTop() : origin.offset().top;
             var originLeft = isFixed ? origin.offset().left - $(document).scrollLeft() : origin.offset().left;
   
             // Calculating screen
             var windowWidth = $(window).width();
             var windowHeight = $(window).height();
             var centerX = windowWidth / 2;
             var centerY = windowHeight / 2;
             var isLeft = originLeft <= centerX;
             var isRight = originLeft > centerX;
             var isTop = originTop <= centerY;
             var isBottom = originTop > centerY;
             var isCenterX = originLeft >= windowWidth * 0.25 && originLeft <= windowWidth * 0.75;
             var isCenterY = originTop >= windowHeight * 0.25 && originTop <= windowHeight * 0.75;
   
             // Calculating tap target
             var tapTargetWidth = tapTargetEl.outerWidth();
             var tapTargetHeight = tapTargetEl.outerHeight();
             var tapTargetTop = originTop + originHeight / 2 - tapTargetHeight / 2;
             var tapTargetLeft = originLeft + originWidth / 2 - tapTargetWidth / 2;
             var tapTargetPosition = isFixed ? 'fixed' : 'absolute';
   
             // Calculating content
             var tapTargetTextWidth = isCenterX ? tapTargetWidth : tapTargetWidth / 2 + originWidth;
             var tapTargetTextHeight = tapTargetHeight / 2;
             var tapTargetTextTop = isTop ? tapTargetHeight / 2 : 0;
             var tapTargetTextBottom = 0;
             var tapTargetTextLeft = isLeft && !isCenterX ? tapTargetWidth / 2 - originWidth : 0;
             var tapTargetTextRight = 0;
             var tapTargetTextPadding = originWidth;
             var tapTargetTextAlign = isBottom ? 'bottom' : 'top';
   
             // Calculating wave
             var tapTargetWaveWidth = originWidth > originHeight ? originWidth * 2 : originWidth * 2;
             var tapTargetWaveHeight = tapTargetWaveWidth;
             var tapTargetWaveTop = tapTargetHeight / 2 - tapTargetWaveHeight / 2;
             var tapTargetWaveLeft = tapTargetWidth / 2 - tapTargetWaveWidth / 2;
   
             // Setting tap target
             var tapTargetWrapperCssObj = {};
             tapTargetWrapperCssObj.top = isTop ? tapTargetTop : '';
             tapTargetWrapperCssObj.right = isRight ? windowWidth - tapTargetLeft - tapTargetWidth : '';
             tapTargetWrapperCssObj.bottom = isBottom ? windowHeight - tapTargetTop - tapTargetHeight : '';
             tapTargetWrapperCssObj.left = isLeft ? tapTargetLeft : '';
             tapTargetWrapperCssObj.position = tapTargetPosition;
             tapTargetWrapper.css(tapTargetWrapperCssObj);
   
             // Setting content
             tapTargetContentEl.css({
               width: tapTargetTextWidth,
               height: tapTargetTextHeight,
               top: tapTargetTextTop,
               right: tapTargetTextRight,
               bottom: tapTargetTextBottom,
               left: tapTargetTextLeft,
               padding: tapTargetTextPadding,
               verticalAlign: tapTargetTextAlign
             });
   
             // Setting wave
             tapTargetWave.css({
               top: tapTargetWaveTop,
               left: tapTargetWaveLeft,
               width: tapTargetWaveWidth,
               height: tapTargetWaveHeight
             });
           };
   
           if (options == 'open') {
             calculateTapTarget();
             openTapTarget();
           }
   
           if (options == 'close') closeTapTarget();
         });
       },
       open: function () {},
       close: function () {}
     };
   
     $.fn.tapTarget = function (methodOrOptions) {
       if (methods[methodOrOptions] || typeof methodOrOptions === 'object') return methods.init.apply(this, arguments);
   
       $.error('Method ' + methodOrOptions + ' does not exist on jQuery.tap-target');
     };
   })(jQuery);
   
   
   /***/ }),
   /* 7 */
   /***/ (function(module, exports) {
   
   /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {/* globals __webpack_amd_options__ */
   module.exports = __webpack_amd_options__;
   
   /* WEBPACK VAR INJECTION */}.call(exports, {}))
   
   /***/ }),
   /* 8 */
   /***/ (function(module, exports, __webpack_require__) {
   
   var __WEBPACK_AMD_DEFINE_RESULT__;/*! Hammer.JS - v2.0.7 - 2016-04-22
    * http://hammerjs.github.io/
    *
    * Copyright (c) 2016 Jorik Tangelder;
    * Licensed under the MIT license */
   (function(window, document, exportName, undefined) {
     'use strict';
   
   var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
   var TEST_ELEMENT = document.createElement('div');
   
   var TYPE_FUNCTION = 'function';
   
   var round = Math.round;
   var abs = Math.abs;
   var now = Date.now;
   
   /**
    * set a timeout with a given scope
    * @param {Function} fn
    * @param {Number} timeout
    * @param {Object} context
    * @returns {number}
    */
   function setTimeoutContext(fn, timeout, context) {
       return setTimeout(bindFn(fn, context), timeout);
   }
   
   /**
    * if the argument is an array, we want to execute the fn on each entry
    * if it aint an array we don't want to do a thing.
    * this is used by all the methods that accept a single and array argument.
    * @param {*|Array} arg
    * @param {String} fn
    * @param {Object} [context]
    * @returns {Boolean}
    */
   function invokeArrayArg(arg, fn, context) {
       if (Array.isArray(arg)) {
           each(arg, context[fn], context);
           return true;
       }
       return false;
   }
   
   /**
    * walk objects and arrays
    * @param {Object} obj
    * @param {Function} iterator
    * @param {Object} context
    */
   function each(obj, iterator, context) {
       var i;
   
       if (!obj) {
           return;
       }
   
       if (obj.forEach) {
           obj.forEach(iterator, context);
       } else if (obj.length !== undefined) {
           i = 0;
           while (i < obj.length) {
               iterator.call(context, obj[i], i, obj);
               i++;
           }
       } else {
           for (i in obj) {
               obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
           }
       }
   }
   
   /**
    * wrap a method with a deprecation warning and stack trace
    * @param {Function} method
    * @param {String} name
    * @param {String} message
    * @returns {Function} A new function wrapping the supplied method.
    */
   function deprecate(method, name, message) {
       var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
       return function() {
           var e = new Error('get-stack-trace');
           var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
               .replace(/^\s+at\s+/gm, '')
               .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
   
           var log = window.console && (window.console.warn || window.console.log);
           if (log) {
               log.call(window.console, deprecationMessage, stack);
           }
           return method.apply(this, arguments);
       };
   }
   
   /**
    * extend object.
    * means that properties in dest will be overwritten by the ones in src.
    * @param {Object} target
    * @param {...Object} objects_to_assign
    * @returns {Object} target
    */
   var assign;
   if (typeof Object.assign !== 'function') {
       assign = function assign(target) {
           if (target === undefined || target === null) {
               throw new TypeError('Cannot convert undefined or null to object');
           }
   
           var output = Object(target);
           for (var index = 1; index < arguments.length; index++) {
               var source = arguments[index];
               if (source !== undefined && source !== null) {
                   for (var nextKey in source) {
                       if (source.hasOwnProperty(nextKey)) {
                           output[nextKey] = source[nextKey];
                       }
                   }
               }
           }
           return output;
       };
   } else {
       assign = Object.assign;
   }
   
   /**
    * extend object.
    * means that properties in dest will be overwritten by the ones in src.
    * @param {Object} dest
    * @param {Object} src
    * @param {Boolean} [merge=false]
    * @returns {Object} dest
    */
   var extend = deprecate(function extend(dest, src, merge) {
       var keys = Object.keys(src);
       var i = 0;
       while (i < keys.length) {
           if (!merge || (merge && dest[keys[i]] === undefined)) {
               dest[keys[i]] = src[keys[i]];
           }
           i++;
       }
       return dest;
   }, 'extend', 'Use `assign`.');
   
   /**
    * merge the values from src in the dest.
    * means that properties that exist in dest will not be overwritten by src
    * @param {Object} dest
    * @param {Object} src
    * @returns {Object} dest
    */
   var merge = deprecate(function merge(dest, src) {
       return extend(dest, src, true);
   }, 'merge', 'Use `assign`.');
   
   /**
    * simple class inheritance
    * @param {Function} child
    * @param {Function} base
    * @param {Object} [properties]
    */
   function inherit(child, base, properties) {
       var baseP = base.prototype,
           childP;
   
       childP = child.prototype = Object.create(baseP);
       childP.constructor = child;
       childP._super = baseP;
   
       if (properties) {
           assign(childP, properties);
       }
   }
   
   /**
    * simple function bind
    * @param {Function} fn
    * @param {Object} context
    * @returns {Function}
    */
   function bindFn(fn, context) {
       return function boundFn() {
           return fn.apply(context, arguments);
       };
   }
   
   /**
    * let a boolean value also be a function that must return a boolean
    * this first item in args will be used as the context
    * @param {Boolean|Function} val
    * @param {Array} [args]
    * @returns {Boolean}
    */
   function boolOrFn(val, args) {
       if (typeof val == TYPE_FUNCTION) {
           return val.apply(args ? args[0] || undefined : undefined, args);
       }
       return val;
   }
   
   /**
    * use the val2 when val1 is undefined
    * @param {*} val1
    * @param {*} val2
    * @returns {*}
    */
   function ifUndefined(val1, val2) {
       return (val1 === undefined) ? val2 : val1;
   }
   
   /**
    * addEventListener with multiple events at once
    * @param {EventTarget} target
    * @param {String} types
    * @param {Function} handler
    */
   function addEventListeners(target, types, handler) {
       each(splitStr(types), function(type) {
           target.addEventListener(type, handler, false);
       });
   }
   
   /**
    * removeEventListener with multiple events at once
    * @param {EventTarget} target
    * @param {String} types
    * @param {Function} handler
    */
   function removeEventListeners(target, types, handler) {
       each(splitStr(types), function(type) {
           target.removeEventListener(type, handler, false);
       });
   }
   
   /**
    * find if a node is in the given parent
    * @method hasParent
    * @param {HTMLElement} node
    * @param {HTMLElement} parent
    * @return {Boolean} found
    */
   function hasParent(node, parent) {
       while (node) {
           if (node == parent) {
               return true;
           }
           node = node.parentNode;
       }
       return false;
   }
   
   /**
    * small indexOf wrapper
    * @param {String} str
    * @param {String} find
    * @returns {Boolean} found
    */
   function inStr(str, find) {
       return str.indexOf(find) > -1;
   }
   
   /**
    * split string on whitespace
    * @param {String} str
    * @returns {Array} words
    */
   function splitStr(str) {
       return str.trim().split(/\s+/g);
   }
   
   /**
    * find if a array contains the object using indexOf or a simple polyFill
    * @param {Array} src
    * @param {String} find
    * @param {String} [findByKey]
    * @return {Boolean|Number} false when not found, or the index
    */
   function inArray(src, find, findByKey) {
       if (src.indexOf && !findByKey) {
           return src.indexOf(find);
       } else {
           var i = 0;
           while (i < src.length) {
               if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
                   return i;
               }
               i++;
           }
           return -1;
       }
   }
   
   /**
    * convert array-like objects to real arrays
    * @param {Object} obj
    * @returns {Array}
    */
   function toArray(obj) {
       return Array.prototype.slice.call(obj, 0);
   }
   
   /**
    * unique array with objects based on a key (like 'id') or just by the array's value
    * @param {Array} src [{id:1},{id:2},{id:1}]
    * @param {String} [key]
    * @param {Boolean} [sort=False]
    * @returns {Array} [{id:1},{id:2}]
    */
   function uniqueArray(src, key, sort) {
       var results = [];
       var values = [];
       var i = 0;
   
       while (i < src.length) {
           var val = key ? src[i][key] : src[i];
           if (inArray(values, val) < 0) {
               results.push(src[i]);
           }
           values[i] = val;
           i++;
       }
   
       if (sort) {
           if (!key) {
               results = results.sort();
           } else {
               results = results.sort(function sortUniqueArray(a, b) {
                   return a[key] > b[key];
               });
           }
       }
   
       return results;
   }
   
   /**
    * get the prefixed property
    * @param {Object} obj
    * @param {String} property
    * @returns {String|Undefined} prefixed
    */
   function prefixed(obj, property) {
       var prefix, prop;
       var camelProp = property[0].toUpperCase() + property.slice(1);
   
       var i = 0;
       while (i < VENDOR_PREFIXES.length) {
           prefix = VENDOR_PREFIXES[i];
           prop = (prefix) ? prefix + camelProp : property;
   
           if (prop in obj) {
               return prop;
           }
           i++;
       }
       return undefined;
   }
   
   /**
    * get a unique id
    * @returns {number} uniqueId
    */
   var _uniqueId = 1;
   function uniqueId() {
       return _uniqueId++;
   }
   
   /**
    * get the window object of an element
    * @param {HTMLElement} element
    * @returns {DocumentView|Window}
    */
   function getWindowForElement(element) {
       var doc = element.ownerDocument || element;
       return (doc.defaultView || doc.parentWindow || window);
   }
   
   var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
   
   var SUPPORT_TOUCH = ('ontouchstart' in window);
   var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
   var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
   
   var INPUT_TYPE_TOUCH = 'touch';
   var INPUT_TYPE_PEN = 'pen';
   var INPUT_TYPE_MOUSE = 'mouse';
   var INPUT_TYPE_KINECT = 'kinect';
   
   var COMPUTE_INTERVAL = 25;
   
   var INPUT_START = 1;
   var INPUT_MOVE = 2;
   var INPUT_END = 4;
   var INPUT_CANCEL = 8;
   
   var DIRECTION_NONE = 1;
   var DIRECTION_LEFT = 2;
   var DIRECTION_RIGHT = 4;
   var DIRECTION_UP = 8;
   var DIRECTION_DOWN = 16;
   
   var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
   var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
   var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
   
   var PROPS_XY = ['x', 'y'];
   var PROPS_CLIENT_XY = ['clientX', 'clientY'];
   
   /**
    * create new input type manager
    * @param {Manager} manager
    * @param {Function} callback
    * @returns {Input}
    * @constructor
    */
   function Input(manager, callback) {
       var self = this;
       this.manager = manager;
       this.callback = callback;
       this.element = manager.element;
       this.target = manager.options.inputTarget;
   
       // smaller wrapper around the handler, for the scope and the enabled state of the manager,
       // so when disabled the input events are completely bypassed.
       this.domHandler = function(ev) {
           if (boolOrFn(manager.options.enable, [manager])) {
               self.handler(ev);
           }
       };
   
       this.init();
   
   }
   
   Input.prototype = {
       /**
        * should handle the inputEvent data and trigger the callback
        * @virtual
        */
       handler: function() { },
   
       /**
        * bind the events
        */
       init: function() {
           this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
           this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
           this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
       },
   
       /**
        * unbind the events
        */
       destroy: function() {
           this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
           this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
           this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
       }
   };
   
   /**
    * create new input type manager
    * called by the Manager constructor
    * @param {Hammer} manager
    * @returns {Input}
    */
   function createInputInstance(manager) {
       var Type;
       var inputClass = manager.options.inputClass;
   
       if (inputClass) {
           Type = inputClass;
       } else if (SUPPORT_POINTER_EVENTS) {
           Type = PointerEventInput;
       } else if (SUPPORT_ONLY_TOUCH) {
           Type = TouchInput;
       } else if (!SUPPORT_TOUCH) {
           Type = MouseInput;
       } else {
           Type = TouchMouseInput;
       }
       return new (Type)(manager, inputHandler);
   }
   
   /**
    * handle input events
    * @param {Manager} manager
    * @param {String} eventType
    * @param {Object} input
    */
   function inputHandler(manager, eventType, input) {
       var pointersLen = input.pointers.length;
       var changedPointersLen = input.changedPointers.length;
       var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
       var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
   
       input.isFirst = !!isFirst;
       input.isFinal = !!isFinal;
   
       if (isFirst) {
           manager.session = {};
       }
   
       // source event is the normalized value of the domEvents
       // like 'touchstart, mouseup, pointerdown'
       input.eventType = eventType;
   
       // compute scale, rotation etc
       computeInputData(manager, input);
   
       // emit secret event
       manager.emit('hammer.input', input);
   
       manager.recognize(input);
       manager.session.prevInput = input;
   }
   
   /**
    * extend the data with some usable properties like scale, rotate, velocity etc
    * @param {Object} manager
    * @param {Object} input
    */
   function computeInputData(manager, input) {
       var session = manager.session;
       var pointers = input.pointers;
       var pointersLength = pointers.length;
   
       // store the first input to calculate the distance and direction
       if (!session.firstInput) {
           session.firstInput = simpleCloneInputData(input);
       }
   
       // to compute scale and rotation we need to store the multiple touches
       if (pointersLength > 1 && !session.firstMultiple) {
           session.firstMultiple = simpleCloneInputData(input);
       } else if (pointersLength === 1) {
           session.firstMultiple = false;
       }
   
       var firstInput = session.firstInput;
       var firstMultiple = session.firstMultiple;
       var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
   
       var center = input.center = getCenter(pointers);
       input.timeStamp = now();
       input.deltaTime = input.timeStamp - firstInput.timeStamp;
   
       input.angle = getAngle(offsetCenter, center);
       input.distance = getDistance(offsetCenter, center);
   
       computeDeltaXY(session, input);
       input.offsetDirection = getDirection(input.deltaX, input.deltaY);
   
       var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
       input.overallVelocityX = overallVelocity.x;
       input.overallVelocityY = overallVelocity.y;
       input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
   
       input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
       input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
   
       input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
           session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
   
       computeIntervalInputData(session, input);
   
       // find the correct target
       var target = manager.element;
       if (hasParent(input.srcEvent.target, target)) {
           target = input.srcEvent.target;
       }
       input.target = target;
   }
   
   function computeDeltaXY(session, input) {
       var center = input.center;
       var offset = session.offsetDelta || {};
       var prevDelta = session.prevDelta || {};
       var prevInput = session.prevInput || {};
   
       if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
           prevDelta = session.prevDelta = {
               x: prevInput.deltaX || 0,
               y: prevInput.deltaY || 0
           };
   
           offset = session.offsetDelta = {
               x: center.x,
               y: center.y
           };
       }
   
       input.deltaX = prevDelta.x + (center.x - offset.x);
       input.deltaY = prevDelta.y + (center.y - offset.y);
   }
   
   /**
    * velocity is calculated every x ms
    * @param {Object} session
    * @param {Object} input
    */
   function computeIntervalInputData(session, input) {
       var last = session.lastInterval || input,
           deltaTime = input.timeStamp - last.timeStamp,
           velocity, velocityX, velocityY, direction;
   
       if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
           var deltaX = input.deltaX - last.deltaX;
           var deltaY = input.deltaY - last.deltaY;
   
           var v = getVelocity(deltaTime, deltaX, deltaY);
           velocityX = v.x;
           velocityY = v.y;
           velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
           direction = getDirection(deltaX, deltaY);
   
           session.lastInterval = input;
       } else {
           // use latest velocity info if it doesn't overtake a minimum period
           velocity = last.velocity;
           velocityX = last.velocityX;
           velocityY = last.velocityY;
           direction = last.direction;
       }
   
       input.velocity = velocity;
       input.velocityX = velocityX;
       input.velocityY = velocityY;
       input.direction = direction;
   }
   
   /**
    * create a simple clone from the input used for storage of firstInput and firstMultiple
    * @param {Object} input
    * @returns {Object} clonedInputData
    */
   function simpleCloneInputData(input) {
       // make a simple copy of the pointers because we will get a reference if we don't
       // we only need clientXY for the calculations
       var pointers = [];
       var i = 0;
       while (i < input.pointers.length) {
           pointers[i] = {
               clientX: round(input.pointers[i].clientX),
               clientY: round(input.pointers[i].clientY)
           };
           i++;
       }
   
       return {
           timeStamp: now(),
           pointers: pointers,
           center: getCenter(pointers),
           deltaX: input.deltaX,
           deltaY: input.deltaY
       };
   }
   
   /**
    * get the center of all the pointers
    * @param {Array} pointers
    * @return {Object} center contains `x` and `y` properties
    */
   function getCenter(pointers) {
       var pointersLength = pointers.length;
   
       // no need to loop when only one touch
       if (pointersLength === 1) {
           return {
               x: round(pointers[0].clientX),
               y: round(pointers[0].clientY)
           };
       }
   
       var x = 0, y = 0, i = 0;
       while (i < pointersLength) {
           x += pointers[i].clientX;
           y += pointers[i].clientY;
           i++;
       }
   
       return {
           x: round(x / pointersLength),
           y: round(y / pointersLength)
       };
   }
   
   /**
    * calculate the velocity between two points. unit is in px per ms.
    * @param {Number} deltaTime
    * @param {Number} x
    * @param {Number} y
    * @return {Object} velocity `x` and `y`
    */
   function getVelocity(deltaTime, x, y) {
       return {
           x: x / deltaTime || 0,
           y: y / deltaTime || 0
       };
   }
   
   /**
    * get the direction between two points
    * @param {Number} x
    * @param {Number} y
    * @return {Number} direction
    */
   function getDirection(x, y) {
       if (x === y) {
           return DIRECTION_NONE;
       }
   
       if (abs(x) >= abs(y)) {
           return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
       }
       return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
   }
   
   /**
    * calculate the absolute distance between two points
    * @param {Object} p1 {x, y}
    * @param {Object} p2 {x, y}
    * @param {Array} [props] containing x and y keys
    * @return {Number} distance
    */
   function getDistance(p1, p2, props) {
       if (!props) {
           props = PROPS_XY;
       }
       var x = p2[props[0]] - p1[props[0]],
           y = p2[props[1]] - p1[props[1]];
   
       return Math.sqrt((x * x) + (y * y));
   }
   
   /**
    * calculate the angle between two coordinates
    * @param {Object} p1
    * @param {Object} p2
    * @param {Array} [props] containing x and y keys
    * @return {Number} angle
    */
   function getAngle(p1, p2, props) {
       if (!props) {
           props = PROPS_XY;
       }
       var x = p2[props[0]] - p1[props[0]],
           y = p2[props[1]] - p1[props[1]];
       return Math.atan2(y, x) * 180 / Math.PI;
   }
   
   /**
    * calculate the rotation degrees between two pointersets
    * @param {Array} start array of pointers
    * @param {Array} end array of pointers
    * @return {Number} rotation
    */
   function getRotation(start, end) {
       return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
   }
   
   /**
    * calculate the scale factor between two pointersets
    * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
    * @param {Array} start array of pointers
    * @param {Array} end array of pointers
    * @return {Number} scale
    */
   function getScale(start, end) {
       return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
   }
   
   var MOUSE_INPUT_MAP = {
       mousedown: INPUT_START,
       mousemove: INPUT_MOVE,
       mouseup: INPUT_END
   };
   
   var MOUSE_ELEMENT_EVENTS = 'mousedown';
   var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
   
   /**
    * Mouse events input
    * @constructor
    * @extends Input
    */
   function MouseInput() {
       this.evEl = MOUSE_ELEMENT_EVENTS;
       this.evWin = MOUSE_WINDOW_EVENTS;
   
       this.pressed = false; // mousedown state
   
       Input.apply(this, arguments);
   }
   
   inherit(MouseInput, Input, {
       /**
        * handle mouse events
        * @param {Object} ev
        */
       handler: function MEhandler(ev) {
           var eventType = MOUSE_INPUT_MAP[ev.type];
   
           // on start we want to have the left mouse button down
           if (eventType & INPUT_START && ev.button === 0) {
               this.pressed = true;
           }
   
           if (eventType & INPUT_MOVE && ev.which !== 1) {
               eventType = INPUT_END;
           }
   
           // mouse must be down
           if (!this.pressed) {
               return;
           }
   
           if (eventType & INPUT_END) {
               this.pressed = false;
           }
   
           this.callback(this.manager, eventType, {
               pointers: [ev],
               changedPointers: [ev],
               pointerType: INPUT_TYPE_MOUSE,
               srcEvent: ev
           });
       }
   });
   
   var POINTER_INPUT_MAP = {
       pointerdown: INPUT_START,
       pointermove: INPUT_MOVE,
       pointerup: INPUT_END,
       pointercancel: INPUT_CANCEL,
       pointerout: INPUT_CANCEL
   };
   
   // in IE10 the pointer types is defined as an enum
   var IE10_POINTER_TYPE_ENUM = {
       2: INPUT_TYPE_TOUCH,
       3: INPUT_TYPE_PEN,
       4: INPUT_TYPE_MOUSE,
       5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
   };
   
   var POINTER_ELEMENT_EVENTS = 'pointerdown';
   var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
   
   // IE10 has prefixed support, and case-sensitive
   if (window.MSPointerEvent && !window.PointerEvent) {
       POINTER_ELEMENT_EVENTS = 'MSPointerDown';
       POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
   }
   
   /**
    * Pointer events input
    * @constructor
    * @extends Input
    */
   function PointerEventInput() {
       this.evEl = POINTER_ELEMENT_EVENTS;
       this.evWin = POINTER_WINDOW_EVENTS;
   
       Input.apply(this, arguments);
   
       this.store = (this.manager.session.pointerEvents = []);
   }
   
   inherit(PointerEventInput, Input, {
       /**
        * handle mouse events
        * @param {Object} ev
        */
       handler: function PEhandler(ev) {
           var store = this.store;
           var removePointer = false;
   
           var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
           var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
           var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
   
           var isTouch = (pointerType == INPUT_TYPE_TOUCH);
   
           // get index of the event in the store
           var storeIndex = inArray(store, ev.pointerId, 'pointerId');
   
           // start and mouse must be down
           if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
               if (storeIndex < 0) {
                   store.push(ev);
                   storeIndex = store.length - 1;
               }
           } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
               removePointer = true;
           }
   
           // it not found, so the pointer hasn't been down (so it's probably a hover)
           if (storeIndex < 0) {
               return;
           }
   
           // update the event in the store
           store[storeIndex] = ev;
   
           this.callback(this.manager, eventType, {
               pointers: store,
               changedPointers: [ev],
               pointerType: pointerType,
               srcEvent: ev
           });
   
           if (removePointer) {
               // remove from the store
               store.splice(storeIndex, 1);
           }
       }
   });
   
   var SINGLE_TOUCH_INPUT_MAP = {
       touchstart: INPUT_START,
       touchmove: INPUT_MOVE,
       touchend: INPUT_END,
       touchcancel: INPUT_CANCEL
   };
   
   var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
   var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
   
   /**
    * Touch events input
    * @constructor
    * @extends Input
    */
   function SingleTouchInput() {
       this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
       this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
       this.started = false;
   
       Input.apply(this, arguments);
   }
   
   inherit(SingleTouchInput, Input, {
       handler: function TEhandler(ev) {
           var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
   
           // should we handle the touch events?
           if (type === INPUT_START) {
               this.started = true;
           }
   
           if (!this.started) {
               return;
           }
   
           var touches = normalizeSingleTouches.call(this, ev, type);
   
           // when done, reset the started state
           if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
               this.started = false;
           }
   
           this.callback(this.manager, type, {
               pointers: touches[0],
               changedPointers: touches[1],
               pointerType: INPUT_TYPE_TOUCH,
               srcEvent: ev
           });
       }
   });
   
   /**
    * @this {TouchInput}
    * @param {Object} ev
    * @param {Number} type flag
    * @returns {undefined|Array} [all, changed]
    */
   function normalizeSingleTouches(ev, type) {
       var all = toArray(ev.touches);
       var changed = toArray(ev.changedTouches);
   
       if (type & (INPUT_END | INPUT_CANCEL)) {
           all = uniqueArray(all.concat(changed), 'identifier', true);
       }
   
       return [all, changed];
   }
   
   var TOUCH_INPUT_MAP = {
       touchstart: INPUT_START,
       touchmove: INPUT_MOVE,
       touchend: INPUT_END,
       touchcancel: INPUT_CANCEL
   };
   
   var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
   
   /**
    * Multi-user touch events input
    * @constructor
    * @extends Input
    */
   function TouchInput() {
       this.evTarget = TOUCH_TARGET_EVENTS;
       this.targetIds = {};
   
       Input.apply(this, arguments);
   }
   
   inherit(TouchInput, Input, {
       handler: function MTEhandler(ev) {
           var type = TOUCH_INPUT_MAP[ev.type];
           var touches = getTouches.call(this, ev, type);
           if (!touches) {
               return;
           }
   
           this.callback(this.manager, type, {
               pointers: touches[0],
               changedPointers: touches[1],
               pointerType: INPUT_TYPE_TOUCH,
               srcEvent: ev
           });
       }
   });
   
   /**
    * @this {TouchInput}
    * @param {Object} ev
    * @param {Number} type flag
    * @returns {undefined|Array} [all, changed]
    */
   function getTouches(ev, type) {
       var allTouches = toArray(ev.touches);
       var targetIds = this.targetIds;
   
       // when there is only one touch, the process can be simplified
       if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
           targetIds[allTouches[0].identifier] = true;
           return [allTouches, allTouches];
       }
   
       var i,
           targetTouches,
           changedTouches = toArray(ev.changedTouches),
           changedTargetTouches = [],
           target = this.target;
   
       // get target touches from touches
       targetTouches = allTouches.filter(function(touch) {
           return hasParent(touch.target, target);
       });
   
       // collect touches
       if (type === INPUT_START) {
           i = 0;
           while (i < targetTouches.length) {
               targetIds[targetTouches[i].identifier] = true;
               i++;
           }
       }
   
       // filter changed touches to only contain touches that exist in the collected target ids
       i = 0;
       while (i < changedTouches.length) {
           if (targetIds[changedTouches[i].identifier]) {
               changedTargetTouches.push(changedTouches[i]);
           }
   
           // cleanup removed touches
           if (type & (INPUT_END | INPUT_CANCEL)) {
               delete targetIds[changedTouches[i].identifier];
           }
           i++;
       }
   
       if (!changedTargetTouches.length) {
           return;
       }
   
       return [
           // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
           uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
           changedTargetTouches
       ];
   }
   
   /**
    * Combined touch and mouse input
    *
    * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
    * This because touch devices also emit mouse events while doing a touch.
    *
    * @constructor
    * @extends Input
    */
   
   var DEDUP_TIMEOUT = 2500;
   var DEDUP_DISTANCE = 25;
   
   function TouchMouseInput() {
       Input.apply(this, arguments);
   
       var handler = bindFn(this.handler, this);
       this.touch = new TouchInput(this.manager, handler);
       this.mouse = new MouseInput(this.manager, handler);
   
       this.primaryTouch = null;
       this.lastTouches = [];
   }
   
   inherit(TouchMouseInput, Input, {
       /**
        * handle mouse and touch events
        * @param {Hammer} manager
        * @param {String} inputEvent
        * @param {Object} inputData
        */
       handler: function TMEhandler(manager, inputEvent, inputData) {
           var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
               isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
   
           if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
               return;
           }
   
           // when we're in a touch event, record touches to  de-dupe synthetic mouse event
           if (isTouch) {
               recordTouches.call(this, inputEvent, inputData);
           } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
               return;
           }
   
           this.callback(manager, inputEvent, inputData);
       },
   
       /**
        * remove the event listeners
        */
       destroy: function destroy() {
           this.touch.destroy();
           this.mouse.destroy();
       }
   });
   
   function recordTouches(eventType, eventData) {
       if (eventType & INPUT_START) {
           this.primaryTouch = eventData.changedPointers[0].identifier;
           setLastTouch.call(this, eventData);
       } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
           setLastTouch.call(this, eventData);
       }
   }
   
   function setLastTouch(eventData) {
       var touch = eventData.changedPointers[0];
   
       if (touch.identifier === this.primaryTouch) {
           var lastTouch = {x: touch.clientX, y: touch.clientY};
           this.lastTouches.push(lastTouch);
           var lts = this.lastTouches;
           var removeLastTouch = function() {
               var i = lts.indexOf(lastTouch);
               if (i > -1) {
                   lts.splice(i, 1);
               }
           };
           setTimeout(removeLastTouch, DEDUP_TIMEOUT);
       }
   }
   
   function isSyntheticEvent(eventData) {
       var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
       for (var i = 0; i < this.lastTouches.length; i++) {
           var t = this.lastTouches[i];
           var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
           if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
               return true;
           }
       }
       return false;
   }
   
   var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
   var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
   
   // magical touchAction value
   var TOUCH_ACTION_COMPUTE = 'compute';
   var TOUCH_ACTION_AUTO = 'auto';
   var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
   var TOUCH_ACTION_NONE = 'none';
   var TOUCH_ACTION_PAN_X = 'pan-x';
   var TOUCH_ACTION_PAN_Y = 'pan-y';
   var TOUCH_ACTION_MAP = getTouchActionProps();
   
   /**
    * Touch Action
    * sets the touchAction property or uses the js alternative
    * @param {Manager} manager
    * @param {String} value
    * @constructor
    */
   function TouchAction(manager, value) {
       this.manager = manager;
       this.set(value);
   }
   
   TouchAction.prototype = {
       /**
        * set the touchAction value on the element or enable the polyfill
        * @param {String} value
        */
       set: function(value) {
           // find out the touch-action by the event handlers
           if (value == TOUCH_ACTION_COMPUTE) {
               value = this.compute();
           }
   
           if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
               this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
           }
           this.actions = value.toLowerCase().trim();
       },
   
       /**
        * just re-set the touchAction value
        */
       update: function() {
           this.set(this.manager.options.touchAction);
       },
   
       /**
        * compute the value for the touchAction property based on the recognizer's settings
        * @returns {String} value
        */
       compute: function() {
           var actions = [];
           each(this.manager.recognizers, function(recognizer) {
               if (boolOrFn(recognizer.options.enable, [recognizer])) {
                   actions = actions.concat(recognizer.getTouchAction());
               }
           });
           return cleanTouchActions(actions.join(' '));
       },
   
       /**
        * this method is called on each input cycle and provides the preventing of the browser behavior
        * @param {Object} input
        */
       preventDefaults: function(input) {
           var srcEvent = input.srcEvent;
           var direction = input.offsetDirection;
   
           // if the touch action did prevented once this session
           if (this.manager.session.prevented) {
               srcEvent.preventDefault();
               return;
           }
   
           var actions = this.actions;
           var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
           var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
           var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
   
           if (hasNone) {
               //do not prevent defaults if this is a tap gesture
   
               var isTapPointer = input.pointers.length === 1;
               var isTapMovement = input.distance < 2;
               var isTapTouchTime = input.deltaTime < 250;
   
               if (isTapPointer && isTapMovement && isTapTouchTime) {
                   return;
               }
           }
   
           if (hasPanX && hasPanY) {
               // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
               return;
           }
   
           if (hasNone ||
               (hasPanY && direction & DIRECTION_HORIZONTAL) ||
               (hasPanX && direction & DIRECTION_VERTICAL)) {
               return this.preventSrc(srcEvent);
           }
       },
   
       /**
        * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
        * @param {Object} srcEvent
        */
       preventSrc: function(srcEvent) {
           this.manager.session.prevented = true;
           srcEvent.preventDefault();
       }
   };
   
   /**
    * when the touchActions are collected they are not a valid value, so we need to clean things up. *
    * @param {String} actions
    * @returns {*}
    */
   function cleanTouchActions(actions) {
       // none
       if (inStr(actions, TOUCH_ACTION_NONE)) {
           return TOUCH_ACTION_NONE;
       }
   
       var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
       var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
   
       // if both pan-x and pan-y are set (different recognizers
       // for different directions, e.g. horizontal pan but vertical swipe?)
       // we need none (as otherwise with pan-x pan-y combined none of these
       // recognizers will work, since the browser would handle all panning
       if (hasPanX && hasPanY) {
           return TOUCH_ACTION_NONE;
       }
   
       // pan-x OR pan-y
       if (hasPanX || hasPanY) {
           return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
       }
   
       // manipulation
       if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
           return TOUCH_ACTION_MANIPULATION;
       }
   
       return TOUCH_ACTION_AUTO;
   }
   
   function getTouchActionProps() {
       if (!NATIVE_TOUCH_ACTION) {
           return false;
       }
       var touchMap = {};
       var cssSupports = window.CSS && window.CSS.supports;
       ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
   
           // If css.supports is not supported but there is native touch-action assume it supports
           // all values. This is the case for IE 10 and 11.
           touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
       });
       return touchMap;
   }
   
   /**
    * Recognizer flow explained; *
    * All recognizers have the initial state of POSSIBLE when a input session starts.
    * The definition of a input session is from the first input until the last input, with all it's movement in it. *
    * Example session for mouse-input: mousedown -> mousemove -> mouseup
    *
    * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
    * which determines with state it should be.
    *
    * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
    * POSSIBLE to give it another change on the next cycle.
    *
    *               Possible
    *                  |
    *            +-----+---------------+
    *            |                     |
    *      +-----+-----+               |
    *      |           |               |
    *   Failed      Cancelled          |
    *                          +-------+------+
    *                          |              |
    *                      Recognized       Began
    *                                         |
    *                                      Changed
    *                                         |
    *                                  Ended/Recognized
    */
   var STATE_POSSIBLE = 1;
   var STATE_BEGAN = 2;
   var STATE_CHANGED = 4;
   var STATE_ENDED = 8;
   var STATE_RECOGNIZED = STATE_ENDED;
   var STATE_CANCELLED = 16;
   var STATE_FAILED = 32;
   
   /**
    * Recognizer
    * Every recognizer needs to extend from this class.
    * @constructor
    * @param {Object} options
    */
   function Recognizer(options) {
       this.options = assign({}, this.defaults, options || {});
   
       this.id = uniqueId();
   
       this.manager = null;
   
       // default is enable true
       this.options.enable = ifUndefined(this.options.enable, true);
   
       this.state = STATE_POSSIBLE;
   
       this.simultaneous = {};
       this.requireFail = [];
   }
   
   Recognizer.prototype = {
       /**
        * @virtual
        * @type {Object}
        */
       defaults: {},
   
       /**
        * set options
        * @param {Object} options
        * @return {Recognizer}
        */
       set: function(options) {
           assign(this.options, options);
   
           // also update the touchAction, in case something changed about the directions/enabled state
           this.manager && this.manager.touchAction.update();
           return this;
       },
   
       /**
        * recognize simultaneous with an other recognizer.
        * @param {Recognizer} otherRecognizer
        * @returns {Recognizer} this
        */
       recognizeWith: function(otherRecognizer) {
           if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
               return this;
           }
   
           var simultaneous = this.simultaneous;
           otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
           if (!simultaneous[otherRecognizer.id]) {
               simultaneous[otherRecognizer.id] = otherRecognizer;
               otherRecognizer.recognizeWith(this);
           }
           return this;
       },
   
       /**
        * drop the simultaneous link. it doesnt remove the link on the other recognizer.
        * @param {Recognizer} otherRecognizer
        * @returns {Recognizer} this
        */
       dropRecognizeWith: function(otherRecognizer) {
           if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
               return this;
           }
   
           otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
           delete this.simultaneous[otherRecognizer.id];
           return this;
       },
   
       /**
        * recognizer can only run when an other is failing
        * @param {Recognizer} otherRecognizer
        * @returns {Recognizer} this
        */
       requireFailure: function(otherRecognizer) {
           if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
               return this;
           }
   
           var requireFail = this.requireFail;
           otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
           if (inArray(requireFail, otherRecognizer) === -1) {
               requireFail.push(otherRecognizer);
               otherRecognizer.requireFailure(this);
           }
           return this;
       },
   
       /**
        * drop the requireFailure link. it does not remove the link on the other recognizer.
        * @param {Recognizer} otherRecognizer
        * @returns {Recognizer} this
        */
       dropRequireFailure: function(otherRecognizer) {
           if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
               return this;
           }
   
           otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
           var index = inArray(this.requireFail, otherRecognizer);
           if (index > -1) {
               this.requireFail.splice(index, 1);
           }
           return this;
       },
   
       /**
        * has require failures boolean
        * @returns {boolean}
        */
       hasRequireFailures: function() {
           return this.requireFail.length > 0;
       },
   
       /**
        * if the recognizer can recognize simultaneous with an other recognizer
        * @param {Recognizer} otherRecognizer
        * @returns {Boolean}
        */
       canRecognizeWith: function(otherRecognizer) {
           return !!this.simultaneous[otherRecognizer.id];
       },
   
       /**
        * You should use `tryEmit` instead of `emit` directly to check
        * that all the needed recognizers has failed before emitting.
        * @param {Object} input
        */
       emit: function(input) {
           var self = this;
           var state = this.state;
   
           function emit(event) {
               self.manager.emit(event, input);
           }
   
           // 'panstart' and 'panmove'
           if (state < STATE_ENDED) {
               emit(self.options.event + stateStr(state));
           }
   
           emit(self.options.event); // simple 'eventName' events
   
           if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
               emit(input.additionalEvent);
           }
   
           // panend and pancancel
           if (state >= STATE_ENDED) {
               emit(self.options.event + stateStr(state));
           }
       },
   
       /**
        * Check that all the require failure recognizers has failed,
        * if true, it emits a gesture event,
        * otherwise, setup the state to FAILED.
        * @param {Object} input
        */
       tryEmit: function(input) {
           if (this.canEmit()) {
               return this.emit(input);
           }
           // it's failing anyway
           this.state = STATE_FAILED;
       },
   
       /**
        * can we emit?
        * @returns {boolean}
        */
       canEmit: function() {
           var i = 0;
           while (i < this.requireFail.length) {
               if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
                   return false;
               }
               i++;
           }
           return true;
       },
   
       /**
        * update the recognizer
        * @param {Object} inputData
        */
       recognize: function(inputData) {
           // make a new copy of the inputData
           // so we can change the inputData without messing up the other recognizers
           var inputDataClone = assign({}, inputData);
   
           // is is enabled and allow recognizing?
           if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
               this.reset();
               this.state = STATE_FAILED;
               return;
           }
   
           // reset when we've reached the end
           if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
               this.state = STATE_POSSIBLE;
           }
   
           this.state = this.process(inputDataClone);
   
           // the recognizer has recognized a gesture
           // so trigger an event
           if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
               this.tryEmit(inputDataClone);
           }
       },
   
       /**
        * return the state of the recognizer
        * the actual recognizing happens in this method
        * @virtual
        * @param {Object} inputData
        * @returns {Const} STATE
        */
       process: function(inputData) { }, // jshint ignore:line
   
       /**
        * return the preferred touch-action
        * @virtual
        * @returns {Array}
        */
       getTouchAction: function() { },
   
       /**
        * called when the gesture isn't allowed to recognize
        * like when another is being recognized or it is disabled
        * @virtual
        */
       reset: function() { }
   };
   
   /**
    * get a usable string, used as event postfix
    * @param {Const} state
    * @returns {String} state
    */
   function stateStr(state) {
       if (state & STATE_CANCELLED) {
           return 'cancel';
       } else if (state & STATE_ENDED) {
           return 'end';
       } else if (state & STATE_CHANGED) {
           return 'move';
       } else if (state & STATE_BEGAN) {
           return 'start';
       }
       return '';
   }
   
   /**
    * direction cons to string
    * @param {Const} direction
    * @returns {String}
    */
   function directionStr(direction) {
       if (direction == DIRECTION_DOWN) {
           return 'down';
       } else if (direction == DIRECTION_UP) {
           return 'up';
       } else if (direction == DIRECTION_LEFT) {
           return 'left';
       } else if (direction == DIRECTION_RIGHT) {
           return 'right';
       }
       return '';
   }
   
   /**
    * get a recognizer by name if it is bound to a manager
    * @param {Recognizer|String} otherRecognizer
    * @param {Recognizer} recognizer
    * @returns {Recognizer}
    */
   function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
       var manager = recognizer.manager;
       if (manager) {
           return manager.get(otherRecognizer);
       }
       return otherRecognizer;
   }
   
   /**
    * This recognizer is just used as a base for the simple attribute recognizers.
    * @constructor
    * @extends Recognizer
    */
   function AttrRecognizer() {
       Recognizer.apply(this, arguments);
   }
   
   inherit(AttrRecognizer, Recognizer, {
       /**
        * @namespace
        * @memberof AttrRecognizer
        */
       defaults: {
           /**
            * @type {Number}
            * @default 1
            */
           pointers: 1
       },
   
       /**
        * Used to check if it the recognizer receives valid input, like input.distance > 10.
        * @memberof AttrRecognizer
        * @param {Object} input
        * @returns {Boolean} recognized
        */
       attrTest: function(input) {
           var optionPointers = this.options.pointers;
           return optionPointers === 0 || input.pointers.length === optionPointers;
       },
   
       /**
        * Process the input and return the state for the recognizer
        * @memberof AttrRecognizer
        * @param {Object} input
        * @returns {*} State
        */
       process: function(input) {
           var state = this.state;
           var eventType = input.eventType;
   
           var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
           var isValid = this.attrTest(input);
   
           // on cancel input and we've recognized before, return STATE_CANCELLED
           if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
               return state | STATE_CANCELLED;
           } else if (isRecognized || isValid) {
               if (eventType & INPUT_END) {
                   return state | STATE_ENDED;
               } else if (!(state & STATE_BEGAN)) {
                   return STATE_BEGAN;
               }
               return state | STATE_CHANGED;
           }
           return STATE_FAILED;
       }
   });
   
   /**
    * Pan
    * Recognized when the pointer is down and moved in the allowed direction.
    * @constructor
    * @extends AttrRecognizer
    */
   function PanRecognizer() {
       AttrRecognizer.apply(this, arguments);
   
       this.pX = null;
       this.pY = null;
   }
   
   inherit(PanRecognizer, AttrRecognizer, {
       /**
        * @namespace
        * @memberof PanRecognizer
        */
       defaults: {
           event: 'pan',
           threshold: 10,
           pointers: 1,
           direction: DIRECTION_ALL
       },
   
       getTouchAction: function() {
           var direction = this.options.direction;
           var actions = [];
           if (direction & DIRECTION_HORIZONTAL) {
               actions.push(TOUCH_ACTION_PAN_Y);
           }
           if (direction & DIRECTION_VERTICAL) {
               actions.push(TOUCH_ACTION_PAN_X);
           }
           return actions;
       },
   
       directionTest: function(input) {
           var options = this.options;
           var hasMoved = true;
           var distance = input.distance;
           var direction = input.direction;
           var x = input.deltaX;
           var y = input.deltaY;
   
           // lock to axis?
           if (!(direction & options.direction)) {
               if (options.direction & DIRECTION_HORIZONTAL) {
                   direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
                   hasMoved = x != this.pX;
                   distance = Math.abs(input.deltaX);
               } else {
                   direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
                   hasMoved = y != this.pY;
                   distance = Math.abs(input.deltaY);
               }
           }
           input.direction = direction;
           return hasMoved && distance > options.threshold && direction & options.direction;
       },
   
       attrTest: function(input) {
           return AttrRecognizer.prototype.attrTest.call(this, input) &&
               (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
       },
   
       emit: function(input) {
   
           this.pX = input.deltaX;
           this.pY = input.deltaY;
   
           var direction = directionStr(input.direction);
   
           if (direction) {
               input.additionalEvent = this.options.event + direction;
           }
           this._super.emit.call(this, input);
       }
   });
   
   /**
    * Pinch
    * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
    * @constructor
    * @extends AttrRecognizer
    */
   function PinchRecognizer() {
       AttrRecognizer.apply(this, arguments);
   }
   
   inherit(PinchRecognizer, AttrRecognizer, {
       /**
        * @namespace
        * @memberof PinchRecognizer
        */
       defaults: {
           event: 'pinch',
           threshold: 0,
           pointers: 2
       },
   
       getTouchAction: function() {
           return [TOUCH_ACTION_NONE];
       },
   
       attrTest: function(input) {
           return this._super.attrTest.call(this, input) &&
               (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
       },
   
       emit: function(input) {
           if (input.scale !== 1) {
               var inOut = input.scale < 1 ? 'in' : 'out';
               input.additionalEvent = this.options.event + inOut;
           }
           this._super.emit.call(this, input);
       }
   });
   
   /**
    * Press
    * Recognized when the pointer is down for x ms without any movement.
    * @constructor
    * @extends Recognizer
    */
   function PressRecognizer() {
       Recognizer.apply(this, arguments);
   
       this._timer = null;
       this._input = null;
   }
   
   inherit(PressRecognizer, Recognizer, {
       /**
        * @namespace
        * @memberof PressRecognizer
        */
       defaults: {
           event: 'press',
           pointers: 1,
           time: 251, // minimal time of the pointer to be pressed
           threshold: 9 // a minimal movement is ok, but keep it low
       },
   
       getTouchAction: function() {
           return [TOUCH_ACTION_AUTO];
       },
   
       process: function(input) {
           var options = this.options;
           var validPointers = input.pointers.length === options.pointers;
           var validMovement = input.distance < options.threshold;
           var validTime = input.deltaTime > options.time;
   
           this._input = input;
   
           // we only allow little movement
           // and we've reached an end event, so a tap is possible
           if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
               this.reset();
           } else if (input.eventType & INPUT_START) {
               this.reset();
               this._timer = setTimeoutContext(function() {
                   this.state = STATE_RECOGNIZED;
                   this.tryEmit();
               }, options.time, this);
           } else if (input.eventType & INPUT_END) {
               return STATE_RECOGNIZED;
           }
           return STATE_FAILED;
       },
   
       reset: function() {
           clearTimeout(this._timer);
       },
   
       emit: function(input) {
           if (this.state !== STATE_RECOGNIZED) {
               return;
           }
   
           if (input && (input.eventType & INPUT_END)) {
               this.manager.emit(this.options.event + 'up', input);
           } else {
               this._input.timeStamp = now();
               this.manager.emit(this.options.event, this._input);
           }
       }
   });
   
   /**
    * Rotate
    * Recognized when two or more pointer are moving in a circular motion.
    * @constructor
    * @extends AttrRecognizer
    */
   function RotateRecognizer() {
       AttrRecognizer.apply(this, arguments);
   }
   
   inherit(RotateRecognizer, AttrRecognizer, {
       /**
        * @namespace
        * @memberof RotateRecognizer
        */
       defaults: {
           event: 'rotate',
           threshold: 0,
           pointers: 2
       },
   
       getTouchAction: function() {
           return [TOUCH_ACTION_NONE];
       },
   
       attrTest: function(input) {
           return this._super.attrTest.call(this, input) &&
               (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
       }
   });
   
   /**
    * Swipe
    * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
    * @constructor
    * @extends AttrRecognizer
    */
   function SwipeRecognizer() {
       AttrRecognizer.apply(this, arguments);
   }
   
   inherit(SwipeRecognizer, AttrRecognizer, {
       /**
        * @namespace
        * @memberof SwipeRecognizer
        */
       defaults: {
           event: 'swipe',
           threshold: 10,
           velocity: 0.3,
           direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
           pointers: 1
       },
   
       getTouchAction: function() {
           return PanRecognizer.prototype.getTouchAction.call(this);
       },
   
       attrTest: function(input) {
           var direction = this.options.direction;
           var velocity;
   
           if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
               velocity = input.overallVelocity;
           } else if (direction & DIRECTION_HORIZONTAL) {
               velocity = input.overallVelocityX;
           } else if (direction & DIRECTION_VERTICAL) {
               velocity = input.overallVelocityY;
           }
   
           return this._super.attrTest.call(this, input) &&
               direction & input.offsetDirection &&
               input.distance > this.options.threshold &&
               input.maxPointers == this.options.pointers &&
               abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
       },
   
       emit: function(input) {
           var direction = directionStr(input.offsetDirection);
           if (direction) {
               this.manager.emit(this.options.event + direction, input);
           }
   
           this.manager.emit(this.options.event, input);
       }
   });
   
   /**
    * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
    * between the given interval and position. The delay option can be used to recognize multi-taps without firing
    * a single tap.
    *
    * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
    * multi-taps being recognized.
    * @constructor
    * @extends Recognizer
    */
   function TapRecognizer() {
       Recognizer.apply(this, arguments);
   
       // previous time and center,
       // used for tap counting
       this.pTime = false;
       this.pCenter = false;
   
       this._timer = null;
       this._input = null;
       this.count = 0;
   }
   
   inherit(TapRecognizer, Recognizer, {
       /**
        * @namespace
        * @memberof PinchRecognizer
        */
       defaults: {
           event: 'tap',
           pointers: 1,
           taps: 1,
           interval: 300, // max time between the multi-tap taps
           time: 250, // max time of the pointer to be down (like finger on the screen)
           threshold: 9, // a minimal movement is ok, but keep it low
           posThreshold: 10 // a multi-tap can be a bit off the initial position
       },
   
       getTouchAction: function() {
           return [TOUCH_ACTION_MANIPULATION];
       },
   
       process: function(input) {
           var options = this.options;
   
           var validPointers = input.pointers.length === options.pointers;
           var validMovement = input.distance < options.threshold;
           var validTouchTime = input.deltaTime < options.time;
   
           this.reset();
   
           if ((input.eventType & INPUT_START) && (this.count === 0)) {
               return this.failTimeout();
           }
   
           // we only allow little movement
           // and we've reached an end event, so a tap is possible
           if (validMovement && validTouchTime && validPointers) {
               if (input.eventType != INPUT_END) {
                   return this.failTimeout();
               }
   
               var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
               var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
   
               this.pTime = input.timeStamp;
               this.pCenter = input.center;
   
               if (!validMultiTap || !validInterval) {
                   this.count = 1;
               } else {
                   this.count += 1;
               }
   
               this._input = input;
   
               // if tap count matches we have recognized it,
               // else it has began recognizing...
               var tapCount = this.count % options.taps;
               if (tapCount === 0) {
                   // no failing requirements, immediately trigger the tap event
                   // or wait as long as the multitap interval to trigger
                   if (!this.hasRequireFailures()) {
                       return STATE_RECOGNIZED;
                   } else {
                       this._timer = setTimeoutContext(function() {
                           this.state = STATE_RECOGNIZED;
                           this.tryEmit();
                       }, options.interval, this);
                       return STATE_BEGAN;
                   }
               }
           }
           return STATE_FAILED;
       },
   
       failTimeout: function() {
           this._timer = setTimeoutContext(function() {
               this.state = STATE_FAILED;
           }, this.options.interval, this);
           return STATE_FAILED;
       },
   
       reset: function() {
           clearTimeout(this._timer);
       },
   
       emit: function() {
           if (this.state == STATE_RECOGNIZED) {
               this._input.tapCount = this.count;
               this.manager.emit(this.options.event, this._input);
           }
       }
   });
   
   /**
    * Simple way to create a manager with a default set of recognizers.
    * @param {HTMLElement} element
    * @param {Object} [options]
    * @constructor
    */
   function Hammer(element, options) {
       options = options || {};
       options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
       return new Manager(element, options);
   }
   
   /**
    * @const {string}
    */
   Hammer.VERSION = '2.0.7';
   
   /**
    * default settings
    * @namespace
    */
   Hammer.defaults = {
       /**
        * set if DOM events are being triggered.
        * But this is slower and unused by simple implementations, so disabled by default.
        * @type {Boolean}
        * @default false
        */
       domEvents: false,
   
       /**
        * The value for the touchAction property/fallback.
        * When set to `compute` it will magically set the correct value based on the added recognizers.
        * @type {String}
        * @default compute
        */
       touchAction: TOUCH_ACTION_COMPUTE,
   
       /**
        * @type {Boolean}
        * @default true
        */
       enable: true,
   
       /**
        * EXPERIMENTAL FEATURE -- can be removed/changed
        * Change the parent input target element.
        * If Null, then it is being set the to main element.
        * @type {Null|EventTarget}
        * @default null
        */
       inputTarget: null,
   
       /**
        * force an input class
        * @type {Null|Function}
        * @default null
        */
       inputClass: null,
   
       /**
        * Default recognizer setup when calling `Hammer()`
        * When creating a new Manager these will be skipped.
        * @type {Array}
        */
       preset: [
           // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
           [RotateRecognizer, {enable: false}],
           [PinchRecognizer, {enable: false}, ['rotate']],
           [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
           [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
           [TapRecognizer],
           [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
           [PressRecognizer]
       ],
   
       /**
        * Some CSS properties can be used to improve the working of Hammer.
        * Add them to this method and they will be set when creating a new Manager.
        * @namespace
        */
       cssProps: {
           /**
            * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
            * @type {String}
            * @default 'none'
            */
           userSelect: 'none',
   
           /**
            * Disable the Windows Phone grippers when pressing an element.
            * @type {String}
            * @default 'none'
            */
           touchSelect: 'none',
   
           /**
            * Disables the default callout shown when you touch and hold a touch target.
            * On iOS, when you touch and hold a touch target such as a link, Safari displays
            * a callout containing information about the link. This property allows you to disable that callout.
            * @type {String}
            * @default 'none'
            */
           touchCallout: 'none',
   
           /**
            * Specifies whether zooming is enabled. Used by IE10>
            * @type {String}
            * @default 'none'
            */
           contentZooming: 'none',
   
           /**
            * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
            * @type {String}
            * @default 'none'
            */
           userDrag: 'none',
   
           /**
            * Overrides the highlight color shown when the user taps a link or a JavaScript
            * clickable element in iOS. This property obeys the alpha value, if specified.
            * @type {String}
            * @default 'rgba(0,0,0,0)'
            */
           tapHighlightColor: 'rgba(0,0,0,0)'
       }
   };
   
   var STOP = 1;
   var FORCED_STOP = 2;
   
   /**
    * Manager
    * @param {HTMLElement} element
    * @param {Object} [options]
    * @constructor
    */
   function Manager(element, options) {
       this.options = assign({}, Hammer.defaults, options || {});
   
       this.options.inputTarget = this.options.inputTarget || element;
   
       this.handlers = {};
       this.session = {};
       this.recognizers = [];
       this.oldCssProps = {};
   
       this.element = element;
       this.input = createInputInstance(this);
       this.touchAction = new TouchAction(this, this.options.touchAction);
   
       toggleCssProps(this, true);
   
       each(this.options.recognizers, function(item) {
           var recognizer = this.add(new (item[0])(item[1]));
           item[2] && recognizer.recognizeWith(item[2]);
           item[3] && recognizer.requireFailure(item[3]);
       }, this);
   }
   
   Manager.prototype = {
       /**
        * set options
        * @param {Object} options
        * @returns {Manager}
        */
       set: function(options) {
           assign(this.options, options);
   
           // Options that need a little more setup
           if (options.touchAction) {
               this.touchAction.update();
           }
           if (options.inputTarget) {
               // Clean up existing event listeners and reinitialize
               this.input.destroy();
               this.input.target = options.inputTarget;
               this.input.init();
           }
           return this;
       },
   
       /**
        * stop recognizing for this session.
        * This session will be discarded, when a new [input]start event is fired.
        * When forced, the recognizer cycle is stopped immediately.
        * @param {Boolean} [force]
        */
       stop: function(force) {
           this.session.stopped = force ? FORCED_STOP : STOP;
       },
   
       /**
        * run the recognizers!
        * called by the inputHandler function on every movement of the pointers (touches)
        * it walks through all the recognizers and tries to detect the gesture that is being made
        * @param {Object} inputData
        */
       recognize: function(inputData) {
           var session = this.session;
           if (session.stopped) {
               return;
           }
   
           // run the touch-action polyfill
           this.touchAction.preventDefaults(inputData);
   
           var recognizer;
           var recognizers = this.recognizers;
   
           // this holds the recognizer that is being recognized.
           // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
           // if no recognizer is detecting a thing, it is set to `null`
           var curRecognizer = session.curRecognizer;
   
           // reset when the last recognizer is recognized
           // or when we're in a new session
           if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
               curRecognizer = session.curRecognizer = null;
           }
   
           var i = 0;
           while (i < recognizers.length) {
               recognizer = recognizers[i];
   
               // find out if we are allowed try to recognize the input for this one.
               // 1.   allow if the session is NOT forced stopped (see the .stop() method)
               // 2.   allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
               //      that is being recognized.
               // 3.   allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
               //      this can be setup with the `recognizeWith()` method on the recognizer.
               if (session.stopped !== FORCED_STOP && ( // 1
                       !curRecognizer || recognizer == curRecognizer || // 2
                       recognizer.canRecognizeWith(curRecognizer))) { // 3
                   recognizer.recognize(inputData);
               } else {
                   recognizer.reset();
               }
   
               // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
               // current active recognizer. but only if we don't already have an active recognizer
               if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
                   curRecognizer = session.curRecognizer = recognizer;
               }
               i++;
           }
       },
   
       /**
        * get a recognizer by its event name.
        * @param {Recognizer|String} recognizer
        * @returns {Recognizer|Null}
        */
       get: function(recognizer) {
           if (recognizer instanceof Recognizer) {
               return recognizer;
           }
   
           var recognizers = this.recognizers;
           for (var i = 0; i < recognizers.length; i++) {
               if (recognizers[i].options.event == recognizer) {
                   return recognizers[i];
               }
           }
           return null;
       },
   
       /**
        * add a recognizer to the manager
        * existing recognizers with the same event name will be removed
        * @param {Recognizer} recognizer
        * @returns {Recognizer|Manager}
        */
       add: function(recognizer) {
           if (invokeArrayArg(recognizer, 'add', this)) {
               return this;
           }
   
           // remove existing
           var existing = this.get(recognizer.options.event);
           if (existing) {
               this.remove(existing);
           }
   
           this.recognizers.push(recognizer);
           recognizer.manager = this;
   
           this.touchAction.update();
           return recognizer;
       },
   
       /**
        * remove a recognizer by name or instance
        * @param {Recognizer|String} recognizer
        * @returns {Manager}
        */
       remove: function(recognizer) {
           if (invokeArrayArg(recognizer, 'remove', this)) {
               return this;
           }
   
           recognizer = this.get(recognizer);
   
           // let's make sure this recognizer exists
           if (recognizer) {
               var recognizers = this.recognizers;
               var index = inArray(recognizers, recognizer);
   
               if (index !== -1) {
                   recognizers.splice(index, 1);
                   this.touchAction.update();
               }
           }
   
           return this;
       },
   
       /**
        * bind event
        * @param {String} events
        * @param {Function} handler
        * @returns {EventEmitter} this
        */
       on: function(events, handler) {
           if (events === undefined) {
               return;
           }
           if (handler === undefined) {
               return;
           }
   
           var handlers = this.handlers;
           each(splitStr(events), function(event) {
               handlers[event] = handlers[event] || [];
               handlers[event].push(handler);
           });
           return this;
       },
   
       /**
        * unbind event, leave emit blank to remove all handlers
        * @param {String} events
        * @param {Function} [handler]
        * @returns {EventEmitter} this
        */
       off: function(events, handler) {
           if (events === undefined) {
               return;
           }
   
           var handlers = this.handlers;
           each(splitStr(events), function(event) {
               if (!handler) {
                   delete handlers[event];
               } else {
                   handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
               }
           });
           return this;
       },
   
       /**
        * emit event to the listeners
        * @param {String} event
        * @param {Object} data
        */
       emit: function(event, data) {
           // we also want to trigger dom events
           if (this.options.domEvents) {
               triggerDomEvent(event, data);
           }
   
           // no handlers, so skip it all
           var handlers = this.handlers[event] && this.handlers[event].slice();
           if (!handlers || !handlers.length) {
               return;
           }
   
           data.type = event;
           data.preventDefault = function() {
               data.srcEvent.preventDefault();
           };
   
           var i = 0;
           while (i < handlers.length) {
               handlers[i](data);
               i++;
           }
       },
   
       /**
        * destroy the manager and unbinds all events
        * it doesn't unbind dom events, that is the user own responsibility
        */
       destroy: function() {
           this.element && toggleCssProps(this, false);
   
           this.handlers = {};
           this.session = {};
           this.input.destroy();
           this.element = null;
       }
   };
   
   /**
    * add/remove the css properties as defined in manager.options.cssProps
    * @param {Manager} manager
    * @param {Boolean} add
    */
   function toggleCssProps(manager, add) {
       var element = manager.element;
       if (!element.style) {
           return;
       }
       var prop;
       each(manager.options.cssProps, function(value, name) {
           prop = prefixed(element.style, name);
           if (add) {
               manager.oldCssProps[prop] = element.style[prop];
               element.style[prop] = value;
           } else {
               element.style[prop] = manager.oldCssProps[prop] || '';
           }
       });
       if (!add) {
           manager.oldCssProps = {};
       }
   }
   
   /**
    * trigger dom event
    * @param {String} event
    * @param {Object} data
    */
   function triggerDomEvent(event, data) {
       var gestureEvent = document.createEvent('Event');
       gestureEvent.initEvent(event, true, true);
       gestureEvent.gesture = data;
       data.target.dispatchEvent(gestureEvent);
   }
   
   assign(Hammer, {
       INPUT_START: INPUT_START,
       INPUT_MOVE: INPUT_MOVE,
       INPUT_END: INPUT_END,
       INPUT_CANCEL: INPUT_CANCEL,
   
       STATE_POSSIBLE: STATE_POSSIBLE,
       STATE_BEGAN: STATE_BEGAN,
       STATE_CHANGED: STATE_CHANGED,
       STATE_ENDED: STATE_ENDED,
       STATE_RECOGNIZED: STATE_RECOGNIZED,
       STATE_CANCELLED: STATE_CANCELLED,
       STATE_FAILED: STATE_FAILED,
   
       DIRECTION_NONE: DIRECTION_NONE,
       DIRECTION_LEFT: DIRECTION_LEFT,
       DIRECTION_RIGHT: DIRECTION_RIGHT,
       DIRECTION_UP: DIRECTION_UP,
       DIRECTION_DOWN: DIRECTION_DOWN,
       DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
       DIRECTION_VERTICAL: DIRECTION_VERTICAL,
       DIRECTION_ALL: DIRECTION_ALL,
   
       Manager: Manager,
       Input: Input,
       TouchAction: TouchAction,
   
       TouchInput: TouchInput,
       MouseInput: MouseInput,
       PointerEventInput: PointerEventInput,
       TouchMouseInput: TouchMouseInput,
       SingleTouchInput: SingleTouchInput,
   
       Recognizer: Recognizer,
       AttrRecognizer: AttrRecognizer,
       Tap: TapRecognizer,
       Pan: PanRecognizer,
       Swipe: SwipeRecognizer,
       Pinch: PinchRecognizer,
       Rotate: RotateRecognizer,
       Press: PressRecognizer,
   
       on: addEventListeners,
       off: removeEventListeners,
       each: each,
       merge: merge,
       extend: extend,
       assign: assign,
       inherit: inherit,
       bindFn: bindFn,
       prefixed: prefixed
   });
   
   // this prevents errors when Hammer is loaded in the presence of an AMD
   //  style loader but by script tag, not by the loader.
   var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
   freeGlobal.Hammer = Hammer;
   
   if (true) {
       !(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
           return Hammer;
       }.call(exports, __webpack_require__, exports, module),
                   __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
   } else if (typeof module != 'undefined' && module.exports) {
       module.exports = Hammer;
   } else {
       window[exportName] = Hammer;
   }
   
   })(window, document, 'Hammer');
   
   
   /***/ })
   /******/ ]);





// makes an ajax call
// if ccw_admin_sidebar_card option is not set or not equal to hide
//  then show the card  - set display: block
jQuery.post(
    ajaxurl, 
    {
        'action': 'ccw_admin_sidebar',
    }, 
    function(response){
        if ( 'hide' !== response ) {
            var wca_card = document.querySelector(".wca_card");
            if ( wca_card ) {
                wca_card.style.display = "block";
            }
        }
    }
);


// when clicked on hide card at admin sidebar
// makes an ajax call an update / create the ccw_admin_sidebar_card option to hide
function ccw_hide_admin_sidebar_card() {

    jQuery.post(
        ajaxurl, 
        {
            'action': 'ccw_hide_admin_sidebar_card',
        }, 
    );

    var wca_card = document.querySelector(".wca_card");

    if  ( wca_card ) {
        wca_card.style.display = "none";
    }
    
}